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.

./danfe
--- 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;
+    }
+}
+#endif
 
 
 EntangleDeviceManager *entangle_device_manager_new(void)
@@ -138,6 +239,8 @@ static void entangle_device_manager_init
 {
     EntangleDeviceManagerPrivate *priv = manager->priv;
     GList *devs, *tmp;
+
+#if defined(__linux__)
     const gchar *const subsys[] = {
         "usb/usb_device", NULL,
     };
@@ -161,6 +264,12 @@ static void entangle_device_manager_init
     }
 
     g_list_free(devs);
+#elif defined(__FreeBSD__)
+
+    ENTANGLE_DEBUG("Init devd");
+
+    devd_init(manager);
+#endif
 }
 
 
--- configure.orig      2013-03-13 05:24:35.000000000 +0800
+++ configure   2013-07-04 17:58:15.000000000 +0800
@@ -12978,100 +12978,6 @@ fi
 
 
 pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GUDEV" >&5
-$as_echo_n "checking for GUDEV... " >&6; }
-
-if test -n "$GUDEV_CFLAGS"; then
-    pkg_cv_GUDEV_CFLAGS="$GUDEV_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists 
--print-errors \"gudev-1.0 >= \$GUDEV_REQUIRED\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gudev-1.0 >= $GUDEV_REQUIRED") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_GUDEV_CFLAGS=`$PKG_CONFIG --cflags "gudev-1.0 >= $GUDEV_REQUIRED" 
2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-if test -n "$GUDEV_LIBS"; then
-    pkg_cv_GUDEV_LIBS="$GUDEV_LIBS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists 
--print-errors \"gudev-1.0 >= \$GUDEV_REQUIRED\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gudev-1.0 >= $GUDEV_REQUIRED") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_GUDEV_LIBS=`$PKG_CONFIG --libs "gudev-1.0 >= $GUDEV_REQUIRED" 
2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               GUDEV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors 
--cflags --libs "gudev-1.0 >= $GUDEV_REQUIRED" 2>&1`
-        else
-               GUDEV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs 
"gudev-1.0 >= $GUDEV_REQUIRED" 2>&1`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$GUDEV_PKG_ERRORS" >&5
-
-       as_fn_error $? "Package requirements (gudev-1.0 >= $GUDEV_REQUIRED) 
were not met:
-
-$GUDEV_PKG_ERRORS
-
-Consider adjusting the PKG_CONFIG_PATH environment variable if you
-installed software in a non-standard prefix.
-
-Alternatively, you may set the environment variables GUDEV_CFLAGS
-and GUDEV_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details." "$LINENO" 5
-elif test $pkg_failed = untried; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "The pkg-config script could not be found or is too old.  Make 
sure it
-is in your PATH or set the PKG_CONFIG environment variable to the full
-path to pkg-config.
-
-Alternatively, you may set the environment variables GUDEV_CFLAGS
-and GUDEV_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details.
-
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.
-See \`config.log' for more details" "$LINENO" 5; }
-else
-       GUDEV_CFLAGS=$pkg_cv_GUDEV_CFLAGS
-       GUDEV_LIBS=$pkg_cv_GUDEV_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-fi
-
-
-
-
-pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBUS_GLIB" >&5
 $as_echo_n "checking for DBUS_GLIB... " >&6; }
 
_______________________________________________
Entangle-devel mailing list
Entangle-devel@gna.org
https://mail.gna.org/listinfo/entangle-devel

Reply via email to