Re: [Entangle-devel] [patch] Port to FreeBSD: udev - devd (for automatic camera detection)
On Mon, Jul 08, 2013 at 08:47:44PM +0100, Daniel P. Berrange wrote: On Fri, Jul 05, 2013 at 08:18:59PM +0700, Alexey Dokuchaev wrote: On Fri, Jul 05, 2013 at 01:48:41PM +0100, Daniel P. Berrange wrote: On Fri, Jul 05, 2013 at 07:16:03PM +0700, Alexey Dokuchaev wrote: [...] What I need to do, is first to reestablish new connection to newly run devd, and then g_io_channel_shutdown(...)/g_object_unref(oldsocket). IMHO the order you have here ought to be ok. My thinking the reason for calling devd_init() first, then cleaning up is because it takes certain time to devd to reappear and start serving again. In indication of this is a series of repeating failing connect() calls if perror()'ing them... But I might be wrong. Yep, that sounds pretty likely indeed. If you get a failure to reconnect to devd, then you can use g_timeout_add to re-schedule an attempt to connect 1 second later, or something like that. [...] Hi Daniel, Sorry I never had time to finish conversion to G* API, but nonetheless, the FreeBSD port seems to work fine (and was recently updated to version 0.6.0). May I ask you to augment Install it from your Linux distribution (others coming soon) text on the http://entangle-photo.org/ to Linux/Unix (or, if you prefer, Linux/BSD) and add the following install command line: # pkg install entangle (FreeBSD) to the Download block? Thanks, ./danfe ___ Entangle-devel mailing list Entangle-devel@gna.org https://mail.gna.org/listinfo/entangle-devel
Re: [Entangle-devel] [patch] Port to FreeBSD: udev - devd (for automatic camera detection)
On Fri, Jul 05, 2013 at 08:18:59PM +0700, Alexey Dokuchaev wrote: On Fri, Jul 05, 2013 at 01:48:41PM +0100, Daniel P. Berrange wrote: On Fri, Jul 05, 2013 at 07:16:03PM +0700, Alexey Dokuchaev wrote: [...] What I need to do, is first to reestablish new connection to newly run devd, and then g_io_channel_shutdown(...)/g_object_unref(oldsocket). IMHO the order you have here ought to be ok. My thinking the reason for calling devd_init() first, then cleaning up is because it takes sertain time to devd to reappear and start serving again. In indication of this is a series of repeating failing connect() calls if perror()'ing them... But I might be wrong. Yep, that sounds pretty likely indeed. If you get a failure to reconnect to devd, then you can use g_timeout_add to re-schedule an attempt to connect 1 second later, or something like that. Can you send the code you currently have, so I can see the bigger picture of how you now have it written. Sure, attached is the current version of entangle-device-manager.c. The code you have looks fine, so I think it just needs to try to do the reschedule to reconnect attempt 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
Re: [Entangle-devel] [patch] Port to FreeBSD: udev - devd (for automatic camera detection)
On Thu, Jul 04, 2013 at 01:35:21PM +0100, Daniel P. Berrange wrote: 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. I've attempted to replace POSIX socket/connect stuff with corresponding g_* calls, but cannot figure out to properly handle devd(8) daemon restarts. It's easy when dealing with raw file descriptors, because IO channel also works over them (not GSockets). See my POSIX code below: +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; Now with GSocket, I'm no longer working with int fd, but with GSocket* priv-ctx (I reused the same name as in Linux, since they both unrefed in the same way, just differ in type). If I replace it with something like this (to avoid caching priv-ctx), once I issue service devd restart, autodetection stops working. :-( if (manager-priv-ctx) { g_io_channel_shutdown(source, FALSE, NULL); g_object_unref(manager-priv-ctx); } devd_init(manager); What I need to do, is first to reestablish new connection to newly run devd, and then g_io_channel_shutdown(...)/g_object_unref(oldsocket). I'm not sure how to correctly emulate old_efd = g_io_channel_unix_get_fd(...) to obtain underlying (old, stray) GSocket. Any ideas how to correctly reopen new socket, and *then* teardown old channel/socket in GIO words? 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. OK, simple patch attached. It also fixes one apparent typo. ./danfe --- configure.ac.orig 2013-03-13 05:23:34.0 +0800 +++ configure.ac2013-07-05 18:45:32.0 +0800 @@ -30,8 +30,6 @@ AC_SUBST(GTK_REQUIRED) GPHOTO2_REQUIRED=2.4.11 AC_SUBST(GPHOTO2_REQUIRED) -GUDEV_REQUIRED=145 -AC_SUBST(GUDEV_REQUIRED) DBUS_GLIB_REQUIRED=0.60 AC_SUBST(DBUS_GLIB_REQUIRED) GOBJECT_INTROSPECTION_REQUIRED=0.9.3 @@ -61,7 +59,7 @@ AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) -PKG_CHECK_MODULES([GIO], [glib-2.0 = $GIO_REQUIRED]) +PKG_CHECK_MODULES([GIO], [gio-2.0 = $GIO_REQUIRED]) AC_SUBST(GIO_CFLAGS) AC_SUBST(GIO_LIBS) @@ -102,9 +100,13 @@ AC_DEFINE_UNQUOTED([HAVE_GPHOTO25], 1, [whether we're building libgphoto = 2.5]) fi -PKG_CHECK_MODULES([GUDEV], [gudev-1.0 = $GUDEV_REQUIRED]) -AC_SUBST(GUDEV_CFLAGS) -AC_SUBST(GUDEV_LIBS) +if test `uname -s` = Linux; then + GUDEV_REQUIRED=145 + AC_SUBST(GUDEV_REQUIRED) + PKG_CHECK_MODULES([GUDEV], [gudev-1.0 = $GUDEV_REQUIRED]) + AC_SUBST(GUDEV_CFLAGS) + AC_SUBST(GUDEV_LIBS) +fi PKG_CHECK_MODULES([DBUS_GLIB], [dbus-glib-1 = $DBUS_GLIB_REQUIRED]) AC_SUBST(DBUS_GLIB_CFLAGS) ___ Entangle-devel mailing list Entangle-devel@gna.org https://mail.gna.org/listinfo/entangle-devel
Re: [Entangle-devel] [patch] Port to FreeBSD: udev - devd (for automatic camera detection)
On Fri, Jul 05, 2013 at 01:48:41PM +0100, Daniel P. Berrange wrote: On Fri, Jul 05, 2013 at 07:16:03PM +0700, Alexey Dokuchaev wrote: [...] What I need to do, is first to reestablish new connection to newly run devd, and then g_io_channel_shutdown(...)/g_object_unref(oldsocket). IMHO the order you have here ought to be ok. My thinking the reason for calling devd_init() first, then cleaning up is because it takes sertain time to devd to reappear and start serving again. In indication of this is a series of repeating failing connect() calls if perror()'ing them... But I might be wrong. Can you send the code you currently have, so I can see the bigger picture of how you now have it written. Sure, attached is the current version of entangle-device-manager.c. ./danfe /* * Entangle: Tethered Camera Control Capture * * Copyright (C) 2009-2012 Daniel P. Berrange * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * */ #include config.h #if defined(__FreeBSD__) #include gio/gio.h #include gio/gunixsocketaddress.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 #define ENTANGLE_DEVICE_MANAGER_GET_PRIVATE(obj)\ (G_TYPE_INSTANCE_GET_PRIVATE((obj), ENTANGLE_TYPE_DEVICE_MANAGER, EntangleDeviceManagerPrivate)) struct _EntangleDeviceManagerPrivate { #if defined(__linux__) GUdevClient #elif defined(__FreeBSD__) GSocket #endif *ctx; }; G_DEFINE_TYPE(EntangleDeviceManager, entangle_device_manager, G_TYPE_OBJECT); static void entangle_device_manager_finalize (GObject *object) { EntangleDeviceManager *manager = ENTANGLE_DEVICE_MANAGER(object); EntangleDeviceManagerPrivate *priv = manager-priv; ENTANGLE_DEBUG(Finalize manager); if (priv-ctx) g_object_unref(priv-ctx); G_OBJECT_CLASS (entangle_device_manager_parent_class)-finalize (object); } static void entangle_device_manager_class_init(EntangleDeviceManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class-finalize = entangle_device_manager_finalize; g_signal_new(device-added, G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(EntangleDeviceManagerClass, device_added), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); g_signal_new(device-removed, G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(EntangleDeviceManagerClass, device_removed), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); g_type_class_add_private(klass, sizeof(EntangleDeviceManagerPrivate)); } #if defined(__linux__) static void do_udev_event(GUdevClient *client G_GNUC_UNUSED, const char *action, GUdevDevice *dev, gpointer opaque) { EntangleDeviceManager *manager = opaque; const gchar *sysfs; const gchar *usbbus, *usbdev; const gchar *devtype; gchar *port; if (strcmp(action, add) != 0 strcmp(action, remove) != 0) return; devtype = g_udev_device_get_devtype(dev); if ((devtype == NULL) || strcmp(devtype, usb_device) != 0) return; sysfs = g_udev_device_get_sysfs_path(dev); usbbus = g_udev_device_get_property(dev, BUSNUM); usbdev = g_udev_device_get_property(dev, DEVNUM); if (sysfs == NULL || usbbus == NULL || usbdev == NULL) return; port = g_strdup_printf(usb:%s,%s, usbbus, usbdev); ENTANGLE_DEBUG(%s device '%s' '%s', action, sysfs, port); if (strcmp(action, add) == 0) { g_signal_emit_by_name(manager, device-added, port); } else { g_signal_emit_by_name(manager, device-removed, port); } g_free(port); } #elif defined(__FreeBSD__) static void devd_init(EntangleDeviceManager *manager); static gboolean do_devd_event(GIOChannel *source, GIOCondition condition,
Re: [Entangle-devel] [patch] Port to FreeBSD: udev - devd (for automatic camera detection)
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.0 +0800 +++ src/backend/entangle-camera-list.c2013-07-04 17:58:15.0 +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.orig2013-03-13 05:23:35.0 +0800 +++ src/backend/entangle-device-manager.c 2013-07-04 20:02:19.0 +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