On Thu, Jul 04, 2013 at 07:27:48PM +0700, Alexey Dokuchaev wrote: > Hi there, > > I've recently discovered Entangle, but was a bit frustrated it's requires > Linuxish udev for automatic camera detection. I've disabled relevant > checks in configure script, and patch two files. Patch is attached, feel > free to ask questions. It should now work under both Linux and FreeBSD.
> --- src/backend/entangle-camera-list.c.orig 2013-03-13 05:23:35.000000000 > +0800 > +++ src/backend/entangle-camera-list.c 2013-07-04 17:58:15.000000000 > +0800 > @@ -117,7 +117,7 @@ static void entangle_camera_list_finaliz > } > > > -static void entangle_camera_list_udev_event(EntangleDeviceManager *manager > G_GNUC_UNUSED, > +static void entangle_camera_list_event(EntangleDeviceManager *manager > G_GNUC_UNUSED, > char *port G_GNUC_UNUSED, > gpointer opaque) > { > @@ -227,9 +227,9 @@ static void entangle_camera_list_init(En > g_error(_("Cannot load gphoto2 ports")); > > g_signal_connect(priv->devManager, "device-added", > - G_CALLBACK(entangle_camera_list_udev_event), list); > + G_CALLBACK(entangle_camera_list_event), list); > g_signal_connect(priv->devManager, "device-removed", > - G_CALLBACK(entangle_camera_list_udev_event), list); > + G_CALLBACK(entangle_camera_list_event), list); > > entangle_camera_list_refresh(list, NULL); > } > --- src/backend/entangle-device-manager.c.orig 2013-03-13 > 05:23:35.000000000 +0800 > +++ src/backend/entangle-device-manager.c 2013-07-04 20:02:19.000000000 > +0800 > @@ -20,13 +20,19 @@ > > #include <config.h> > > -#include <string.h> > -#include <stdio.h> > - > +#if defined(__FreeBSD__) > +#include <sys/socket.h> > +#include <sys/un.h> > +#include <glib.h> > +#include <unistd.h> > +#else > #define G_UDEV_API_IS_SUBJECT_TO_CHANGE > #ifdef G_UDEV_API_IS_SUBJECT_TO_CHANGE > #include <gudev/gudev.h> > #endif > +#endif > +#include <string.h> > +#include <stdio.h> > > #include "entangle-debug.h" > #include "entangle-device-manager.h" > @@ -35,7 +41,11 @@ > (G_TYPE_INSTANCE_GET_PRIVATE((obj), ENTANGLE_TYPE_DEVICE_MANAGER, > EntangleDeviceManagerPrivate)) > > struct _EntangleDeviceManagerPrivate { > +#if defined(__linux__) > GUdevClient *ctx; > +#elif defined(__FreeBSD__) > + int efd; > +#endif > }; > > G_DEFINE_TYPE(EntangleDeviceManager, entangle_device_manager, G_TYPE_OBJECT); > @@ -47,8 +57,13 @@ static void entangle_device_manager_fina > EntangleDeviceManagerPrivate *priv = manager->priv; > ENTANGLE_DEBUG("Finalize manager"); > > +#if defined(__linux__) > if (priv->ctx) > g_object_unref(priv->ctx); > +#elif defined(__FreeBSD__) > + if (priv->efd) > + close(priv->efd); > +#endif > > G_OBJECT_CLASS (entangle_device_manager_parent_class)->finalize (object); > } > @@ -85,6 +100,7 @@ static void entangle_device_manager_clas > } > > > +#if defined(__linux__) > static void do_udev_event(GUdevClient *client G_GNUC_UNUSED, > const char *action, > GUdevDevice *dev, > @@ -126,6 +142,91 @@ static void do_udev_event(GUdevClient *c > } > g_free(port); > } > +#elif defined(__FreeBSD__) > +static void devd_init(EntangleDeviceManager *manager); > + > +static gboolean do_devd_event(GIOChannel *source, > + GIOCondition condition, > + gpointer user_data) > +{ > + EntangleDeviceManager *manager = user_data; > + char *event, *cutoff; > + gsize end; > + GIOStatus status; > + > + status = g_io_channel_read_line(source, &event, NULL, &end, NULL); > + > + switch (status) { > + case G_IO_STATUS_NORMAL: > + event[end] = '\0'; > + if (strncmp(event + 1, "ugen", 4)) > + break; > + if (!(cutoff = strchr(event + 5, ' '))) > + break; > + *cutoff = '\0'; > + if (*event == '+') { > + g_signal_emit_by_name(manager, "device-added", event + 1); > + } else if (*event == '-') { > + g_signal_emit_by_name(manager, "device-removed", event + 1); > + } > + g_free(event); > + break; > + case G_IO_STATUS_EOF: > + case G_IO_STATUS_AGAIN: > + /* > + * Apparently, devd(8) was reinited (restarted?). Allocate > + * new channel and teardown previous connection. > + */ > + devd_init(manager); > + if (manager->priv->efd > 0) { > + int old_efd = g_io_channel_unix_get_fd(source); > + g_io_channel_shutdown(source, FALSE, NULL); > + close(old_efd); > + return FALSE; > + } > + break; > + case G_IO_STATUS_ERROR: > + default: > + /* XXX: what shall we do? */ > + break; > + } > + return TRUE; > +} > + > + > +static void devd_init(EntangleDeviceManager *manager) > +{ > + EntangleDeviceManagerPrivate *priv = manager->priv; > + struct sockaddr_un addr; > + > + priv->efd = socket(PF_UNIX, SOCK_STREAM, 0); > + if (priv->efd == -1) { > + perror("socket"); > + return; > + } > + > + addr.sun_family = AF_UNIX; > + strncpy(addr.sun_path, "/var/run/devd.pipe", sizeof(addr.sun_path)); > + > + if (connect(priv->efd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { > + GIOChannel *channel = g_io_channel_unix_new(priv->efd); > + g_io_add_watch(channel, G_IO_IN, do_devd_event, manager); > + /* > + * We can reduce the refcount here so that when the watch is > + * removed, the channel will be destroyed. > + */ > + g_io_channel_unref(channel); > + } else { > + /* > + * XXX: we should probably spin for a while until connect() > + * succeeds to get rid of the useless socket()/close() storm > + * for a short period when devd(8) is not ready yet. > + */ > + close(priv->efd); > + priv->efd = -1; > + } > +} Hmm, I'd have a slight preference for use of GIO's GSocket + GUnixSocketAddress APIs, rather than directly accessing the POSIX sockets APIs, if you're willing to rewrite to them. > --- configure.orig 2013-03-13 05:24:35.000000000 +0800 > +++ configure 2013-07-04 17:58:15.000000000 +0800 > @@ -12978,100 +12978,6 @@ fi configure is actually an auto-generated file. The master source is in configure.ac You'll want to conditionalize the call to PKG_CHECK_MODULES([GUDEV], [gudev-1.0 >= $GUDEV_REQUIRED]) in that file instead. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| _______________________________________________ Entangle-devel mailing list Entangle-devel@gna.org https://mail.gna.org/listinfo/entangle-devel