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

Reply via email to