From 6400b739ecdf0e14ad3cc1c6c7032a4eb486bb0e Mon Sep 17 00:00:00 2001 From: Marco Barisione Date: Mon, 29 Jul 2013 16:07:52 +0100 Subject: cheese-camera-device-monitor: move from Empathy to tp-account-widgets This commit also changes the licence of the moved code from GPL to LGPL. See GOSSIP-RELICENSING.txt for details. https://bugzilla.gnome.org/show_bug.cgi?id=699492 --- libempathy/Makefile.am | 2 +- libempathy/cheese-camera-device-monitor.c | 407 ---------------------- libempathy/cheese-camera-device-monitor.h | 68 ---- libempathy/empathy-camera-monitor.c | 12 +- tp-account-widgets/Makefile.am | 11 + tp-account-widgets/cheese-camera-device-monitor.c | 406 +++++++++++++++++++++ tp-account-widgets/cheese-camera-device-monitor.h | 67 ++++ 7 files changed, 491 insertions(+), 482 deletions(-) delete mode 100644 libempathy/cheese-camera-device-monitor.c delete mode 100644 libempathy/cheese-camera-device-monitor.h create mode 100644 tp-account-widgets/cheese-camera-device-monitor.c create mode 100644 tp-account-widgets/cheese-camera-device-monitor.h diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am index b75c35a8a..d6b9faa7b 100644 --- a/libempathy/Makefile.am +++ b/libempathy/Makefile.am @@ -104,7 +104,7 @@ libempathy_la_LDFLAGS = \ libempathy_la_SOURCES = \ $(libempathy_handwritten_source) \ - cheese-camera-device-monitor.c cheese-camera-device-monitor.h + $(NULL) libempathy_la_LIBADD = \ $(top_builddir)/extensions/libemp-extensions.la \ diff --git a/libempathy/cheese-camera-device-monitor.c b/libempathy/cheese-camera-device-monitor.c deleted file mode 100644 index 0e868f2b6..000000000 --- a/libempathy/cheese-camera-device-monitor.c +++ /dev/null @@ -1,407 +0,0 @@ -/* This file is a copy of cheese-camera-device-monitor.c from Empathy. We - * just renamespaced it to avoid conflicts when linking on libcheese. */ -/* - * Copyright © 2007,2008 Jaap Haitsma - * Copyright © 2007-2009 daniel g. siegel - * Copyright © 2008 Ryan Zeigler - * Copyright © 2010 Filippo Argiolas - * - * Licensed under the GNU General Public License Version 2 - * - * 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 2 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 . - */ -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#include - -#ifdef HAVE_UDEV - #define G_UDEV_API_IS_SUBJECT_TO_CHANGE 1 - #include -#else - #include - #include - #include - #if USE_SYS_VIDEOIO_H > 0 - #include - #include - #elif defined (__sun) - #include - #include - #endif /* USE_SYS_VIDEOIO_H */ -#endif - -#include "cheese-camera-device-monitor.h" - -/** - * SECTION:cheese-camera-device-monitor - * @short_description: Simple object to enumerate v4l devices - * @include: cheese/cheese-camera-device-monitor.h - * - * #EmpathyCameraDeviceMonitor provides a basic interface for - * video4linux device enumeration and hotplugging. - * - * It uses either GUdev or some platform specific code to list video - * devices. It is also capable (right now in linux only, with the - * udev backend) to monitor device plugging and emit a - * EmpathyCameraDeviceMonitor::added or - * EmpathyCameraDeviceMonitor::removed signal when an event happens. - */ - -G_DEFINE_TYPE (EmpathyCameraDeviceMonitor, empathy_camera_device_monitor, G_TYPE_OBJECT) - -#define EMPATHY_CAMERA_DEVICE_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - EMPATHY_TYPE_CAMERA_DEVICE_MONITOR, \ - EmpathyCameraDeviceMonitorPrivate)) - -#define EMPATHY_CAMERA_DEVICE_MONITOR_ERROR empathy_camera_device_monitor_error_quark () - -#define DEBUG_FLAG EMPATHY_DEBUG_OTHER -#include "empathy-debug.h" - -enum EmpathyCameraDeviceMonitorError -{ - EMPATHY_CAMERA_DEVICE_MONITOR_ERROR_UNKNOWN, - EMPATHY_CAMERA_DEVICE_MONITOR_ERROR_ELEMENT_NOT_FOUND -}; - -typedef struct -{ -#ifdef HAVE_UDEV - GUdevClient *client; -#else - guint filler; -#endif /* HAVE_UDEV */ -} EmpathyCameraDeviceMonitorPrivate; - -enum -{ - ADDED, - REMOVED, - LAST_SIGNAL -}; - -static guint monitor_signals[LAST_SIGNAL]; - -#if 0 -GQuark -empathy_camera_device_monitor_error_quark (void) -{ - return g_quark_from_static_string ("empathy-camera-error-quark"); -} -#endif - -#ifdef HAVE_UDEV -static void -empathy_camera_device_monitor_added (EmpathyCameraDeviceMonitor *monitor, - GUdevDevice *udevice) -{ - const char *device_file; - const char *product_name; - const char *vendor; - const char *product; - const char *bus; - gint vendor_id = 0; - gint product_id = 0; - gint v4l_version = 0; - - const gchar *devpath = g_udev_device_get_property (udevice, "DEVPATH"); - - DEBUG ("Checking udev device '%s'", devpath); - - bus = g_udev_device_get_property (udevice, "ID_BUS"); - if (g_strcmp0 (bus, "usb") == 0) - { - vendor = g_udev_device_get_property (udevice, "ID_VENDOR_ID"); - if (vendor != NULL) - vendor_id = g_ascii_strtoll (vendor, NULL, 16); - product = g_udev_device_get_property (udevice, "ID_MODEL_ID"); - if (product != NULL) - product_id = g_ascii_strtoll (product, NULL, 16); - if (vendor_id == 0 || product_id == 0) - { - DEBUG ("Error getting vendor and product id"); - } - else - { - DEBUG ("Found device %04x:%04x, getting capabilities...", vendor_id, product_id); - } - } - else - { - DEBUG ("Not an usb device, skipping vendor and model id retrieval"); - } - - device_file = g_udev_device_get_device_file (udevice); - if (device_file == NULL) - { - DEBUG ("Error getting V4L device"); - return; - } - - /* vbi devices support capture capability too, but cannot be used, - * so detect them by device name */ - if (strstr (device_file, "vbi")) - { - DEBUG ("Skipping vbi device: %s", device_file); - return; - } - - v4l_version = g_udev_device_get_property_as_int (udevice, "ID_V4L_VERSION"); - if (v4l_version == 2 || v4l_version == 1) - { - const char *caps; - - caps = g_udev_device_get_property (udevice, "ID_V4L_CAPABILITIES"); - if (caps == NULL || strstr (caps, ":capture:") == NULL) - { - DEBUG ("Device %s seems to not have the capture capability, (radio tuner?)" - "Removing it from device list.", device_file); - return; - } - product_name = g_udev_device_get_property (udevice, "ID_V4L_PRODUCT"); - } - else if (v4l_version == 0) - { - DEBUG ("Fix your udev installation to include v4l_id, ignoring %s", device_file); - return; - } - else - { - g_assert_not_reached (); - } - - g_signal_emit (monitor, monitor_signals[ADDED], 0, - devpath, - device_file, - product_name, - v4l_version); -} - -static void -empathy_camera_device_monitor_removed (EmpathyCameraDeviceMonitor *monitor, - GUdevDevice *udevice) -{ - g_signal_emit (monitor, monitor_signals[REMOVED], 0, - g_udev_device_get_property (udevice, "DEVPATH")); -} - -static void -empathy_camera_device_monitor_uevent_cb (GUdevClient *client, - const gchar *action, - GUdevDevice *udevice, - EmpathyCameraDeviceMonitor *monitor) -{ - if (g_str_equal (action, "remove")) - empathy_camera_device_monitor_removed (monitor, udevice); - else if (g_str_equal (action, "add")) - empathy_camera_device_monitor_added (monitor, udevice); -} - -/** - * empathy_camera_device_monitor_coldplug: - * @monitor: a #EmpathyCameraDeviceMonitor object. - * - * Will actively look for plugged in cameras and emit - * ::added for those new cameras. - * This is only required when your program starts, so as to connect - * to those signals before they are emitted. - */ -void -empathy_camera_device_monitor_coldplug (EmpathyCameraDeviceMonitor *monitor) -{ - EmpathyCameraDeviceMonitorPrivate *priv = EMPATHY_CAMERA_DEVICE_MONITOR_GET_PRIVATE (monitor); - GList *devices, *l; - gint i = 0; - - if (priv->client == NULL) - return; - - DEBUG ("Probing devices with udev..."); - - devices = g_udev_client_query_by_subsystem (priv->client, "video4linux"); - - /* Initialize camera structures */ - for (l = devices; l != NULL; l = l->next) - { - empathy_camera_device_monitor_added (monitor, l->data); - g_object_unref (l->data); - i++; - } - g_list_free (devices); - - if (i == 0) DEBUG ("No device found"); -} - -#else /* HAVE_UDEV */ -void -empathy_camera_device_monitor_coldplug (EmpathyCameraDeviceMonitor *monitor) -{ - #if 0 - EmpathyCameraDeviceMonitorPrivate *priv = EMPATHY_CAMERA_DEVICE_MONITOR_GET_PRIVATE (monitor); - struct v4l2_capability v2cap; - struct video_capability v1cap; - int fd, ok; - - if ((fd = open (device_path, O_RDONLY | O_NONBLOCK)) < 0) - { - g_warning ("Failed to open %s: %s", device_path, strerror (errno)); - return; - } - ok = ioctl (fd, VIDIOC_QUERYCAP, &v2cap); - if (ok < 0) - { - ok = ioctl (fd, VIDIOCGCAP, &v1cap); - if (ok < 0) - { - g_warning ("Error while probing v4l capabilities for %s: %s", - device_path, strerror (errno)); - close (fd); - return; - } - g_print ("Detected v4l device: %s\n", v1cap.name); - g_print ("Device type: %d\n", v1cap.type); - gstreamer_src = "v4lsrc"; - product_name = v1cap.name; - } - else - { - guint cap = v2cap.capabilities; - g_print ("Detected v4l2 device: %s\n", v2cap.card); - g_print ("Driver: %s, version: %d\n", v2cap.driver, v2cap.version); - - /* g_print ("Bus info: %s\n", v2cap.bus_info); */ /* Doesn't seem anything useful */ - g_print ("Capabilities: 0x%08X\n", v2cap.capabilities); - if (!(cap & V4L2_CAP_VIDEO_CAPTURE)) - { - g_print ("Device %s seems to not have the capture capability, (radio tuner?)\n" - "Removing it from device list.\n", device_path); - close (fd); - return; - } - gstreamer_src = "v4l2src"; - product_name = (char *) v2cap.card; - } - close (fd); - - GList *devices, *l; - - g_print ("Probing devices with udev...\n"); - - if (priv->client == NULL) - return; - - devices = g_udev_client_query_by_subsystem (priv->client, "video4linux"); - - /* Initialize camera structures */ - for (l = devices; l != NULL; l = l->next) - { - empathy_camera_device_monitor_added (monitor, l->data); - g_object_unref (l->data); - } - g_list_free (devices); - #endif -} - -#endif /* HAVE_UDEV */ - -static void -empathy_camera_device_monitor_finalize (GObject *object) -{ -#ifdef HAVE_UDEV - EmpathyCameraDeviceMonitor *monitor = EMPATHY_CAMERA_DEVICE_MONITOR (object); - EmpathyCameraDeviceMonitorPrivate *priv = EMPATHY_CAMERA_DEVICE_MONITOR_GET_PRIVATE (monitor); - - if (priv->client != NULL) - { - g_object_unref (priv->client); - priv->client = NULL; - } -#endif /* HAVE_UDEV */ - G_OBJECT_CLASS (empathy_camera_device_monitor_parent_class)->finalize (object); -} - -static void -empathy_camera_device_monitor_class_init (EmpathyCameraDeviceMonitorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = empathy_camera_device_monitor_finalize; - - /** - * EmpathyCameraDeviceMonitor::added: - * @device: A private object representing the newly added camera. - * @id: Device unique identifier. - * @device: Device file name (e.g. /dev/video2). - * @product_name: Device product name (human readable, intended to be displayed in a UI). - * @api_version: Supported video4linux API: 1 for v4l, 2 for v4l2. - * - * The ::added signal is emitted when a camera is added, or on start-up - * after #empathy_camera_device_monitor_colplug is called. - **/ - monitor_signals[ADDED] = g_signal_new ("added", G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EmpathyCameraDeviceMonitorClass, added), - NULL, NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); - - /** - * EmpathyCameraDeviceMonitor::removed: - * @device: A private object representing the newly added camera - * @id: Device unique identifier. - * - * The ::removed signal is emitted when a camera is un-plugged, or - * disabled on the system. - **/ - monitor_signals[REMOVED] = g_signal_new ("removed", G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EmpathyCameraDeviceMonitorClass, removed), - NULL, NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, 1, G_TYPE_STRING); - - g_type_class_add_private (klass, sizeof (EmpathyCameraDeviceMonitorPrivate)); -} - -static void -empathy_camera_device_monitor_init (EmpathyCameraDeviceMonitor *monitor) -{ -#ifdef HAVE_UDEV - EmpathyCameraDeviceMonitorPrivate *priv = EMPATHY_CAMERA_DEVICE_MONITOR_GET_PRIVATE (monitor); - const gchar *const subsystems[] = {"video4linux", NULL}; - - priv->client = g_udev_client_new (subsystems); - g_signal_connect (G_OBJECT (priv->client), "uevent", - G_CALLBACK (empathy_camera_device_monitor_uevent_cb), monitor); -#endif /* HAVE_UDEV */ -} - -/** - * empathy_camera_device_monitor_new: - * - * Returns a new #EmpathyCameraDeviceMonitor object. - * - * Return value: a new #EmpathyCameraDeviceMonitor object. - **/ -EmpathyCameraDeviceMonitor * -empathy_camera_device_monitor_new (void) -{ - return g_object_new (EMPATHY_TYPE_CAMERA_DEVICE_MONITOR, NULL); -} - -/* - * vim: sw=2 ts=8 cindent noai bs=2 - */ diff --git a/libempathy/cheese-camera-device-monitor.h b/libempathy/cheese-camera-device-monitor.h deleted file mode 100644 index f3cc3db14..000000000 --- a/libempathy/cheese-camera-device-monitor.h +++ /dev/null @@ -1,68 +0,0 @@ -/* This file is a copy of cheese-camera-device-monitor.h from Empathy. We - * just renamespaced it to avoid conflicts when linking on libcheese. */ -/* - * Copyright © 2007,2008 Jaap Haitsma - * Copyright © 2007-2009 daniel g. siegel - * Copyright © 2008 Ryan zeigler - * - * Licensed under the GNU General Public License Version 2 - * - * 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 2 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 . - */ - - -#ifndef __EMPATHY_CAMERA_DEVICE_MONITOR_H__ -#define __EMPATHY_CAMERA_DEVICE_MONITOR_H__ - -#include - -G_BEGIN_DECLS - -#define EMPATHY_TYPE_CAMERA_DEVICE_MONITOR (empathy_camera_device_monitor_get_type ()) -#define EMPATHY_CAMERA_DEVICE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_CAMERA_DEVICE_MONITOR, \ - EmpathyCameraDeviceMonitor)) -#define EMPATHY_CAMERA_DEVICE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_CAMERA_DEVICE_MONITOR, \ - EmpathyCameraDeviceMonitorClass)) -#define EMPATHY_IS_CAMERA_DEVICE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_CAMERA_DEVICE_MONITOR)) -#define EMPATHY_IS_CAMERA_DEVICE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_CAMERA_DEVICE_MONITOR)) -#define EMPATHY_CAMERA_DEVICE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_CAMERA_DEVICE_MONITOR, \ - EmpathyCameraDeviceMonitorClass)) - -typedef struct _EmpathyCameraDeviceMonitorClass EmpathyCameraDeviceMonitorClass; -typedef struct _EmpathyCameraDeviceMonitor EmpathyCameraDeviceMonitor; - -struct _EmpathyCameraDeviceMonitor -{ - GObject parent; -}; - -struct _EmpathyCameraDeviceMonitorClass -{ - GObjectClass parent_class; - - void (*added)(EmpathyCameraDeviceMonitor *camera, - const char *id, - const char *device_file, - const char *product_name, - int api_version); - void (*removed)(EmpathyCameraDeviceMonitor *camera, const char *id); -}; - -GType empathy_camera_device_monitor_get_type (void) G_GNUC_CONST; -EmpathyCameraDeviceMonitor *empathy_camera_device_monitor_new (void); -void empathy_camera_device_monitor_coldplug (EmpathyCameraDeviceMonitor *monitor); - -G_END_DECLS - -#endif /* __EMPATHY_CAMERA_DEVICE_MONITOR_H__ */ diff --git a/libempathy/empathy-camera-monitor.c b/libempathy/empathy-camera-monitor.c index 6e6691120..cbbd81d4a 100644 --- a/libempathy/empathy-camera-monitor.c +++ b/libempathy/empathy-camera-monitor.c @@ -21,14 +21,14 @@ #include "config.h" #include "empathy-camera-monitor.h" -#include "cheese-camera-device-monitor.h" +#include #define DEBUG_FLAG EMPATHY_DEBUG_OTHER #include "empathy-debug.h" struct _EmpathyCameraMonitorPrivate { - EmpathyCameraDeviceMonitor *empathy_monitor; + TpawCameraDeviceMonitor *empathy_monitor; GQueue *cameras; gint num_cameras; }; @@ -103,7 +103,7 @@ empathy_camera_monitor_free_camera_foreach (gpointer data, } static void -on_camera_added (EmpathyCameraDeviceMonitor *device, +on_camera_added (TpawCameraDeviceMonitor *device, gchar *id, gchar *filename, gchar *product_name, @@ -128,7 +128,7 @@ on_camera_added (EmpathyCameraDeviceMonitor *device, } static void -on_camera_removed (EmpathyCameraDeviceMonitor *device, +on_camera_removed (TpawCameraDeviceMonitor *device, gchar *id, EmpathyCameraMonitor *self) { @@ -205,7 +205,7 @@ empathy_camera_monitor_constructed (GObject *object) G_OBJECT_CLASS (empathy_camera_monitor_parent_class)->constructed (object); - empathy_camera_device_monitor_coldplug (self->priv->empathy_monitor); + tpaw_camera_device_monitor_coldplug (self->priv->empathy_monitor); } static void @@ -247,7 +247,7 @@ empathy_camera_monitor_init (EmpathyCameraMonitor *self) self->priv->cameras = g_queue_new (); - self->priv->empathy_monitor = empathy_camera_device_monitor_new (); + self->priv->empathy_monitor = tpaw_camera_device_monitor_new (); g_signal_connect (self->priv->empathy_monitor, "added", G_CALLBACK (on_camera_added), self); diff --git a/tp-account-widgets/Makefile.am b/tp-account-widgets/Makefile.am index 3aafe3df9..7bbe9f1cc 100644 --- a/tp-account-widgets/Makefile.am +++ b/tp-account-widgets/Makefile.am @@ -7,9 +7,14 @@ AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\"empathy\" \ -DGCR_API_SUBJECT_TO_CHANGE \ $(EMPATHY_CFLAGS) \ + $(UDEV_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) +libtp_account_widgets_LIBADD = \ + $(UDEV_LIBS) \ + $(NULL) + BUILT_SOURCES = \ tpaw-account-widgets-resources.c \ tpaw-account-widgets-resources.h \ @@ -62,6 +67,11 @@ libtp_account_widgets_headers = \ totem-subtitle-encoding.h \ $(NULL) +nocheck_sources = \ + cheese-camera-device-monitor.c \ + cheese-camera-device-monitor.h \ + $(NULL) + pkglib_LTLIBRARIES = libtp-account-widgets.la # libtp-account-widgets's API is not stable and will never be, so use -release to make the @@ -74,6 +84,7 @@ libtp_account_widgets_la_LDFLAGS = \ libtp_account_widgets_la_SOURCES = \ $(libtp_account_widgets_sources) \ $(libtp_account_widgets_headers) \ + $(nocheck_sources) \ $(NULL) # these are sources that depend on Ubuntu Online Accounts diff --git a/tp-account-widgets/cheese-camera-device-monitor.c b/tp-account-widgets/cheese-camera-device-monitor.c new file mode 100644 index 000000000..84e0fc86c --- /dev/null +++ b/tp-account-widgets/cheese-camera-device-monitor.c @@ -0,0 +1,406 @@ +/* This file is a copy of cheese-camera-device-monitor.c from Tpaw. We + * just renamespaced it to avoid conflicts when linking on libcheese. */ +/* + * Copyright © 2007,2008 Jaap Haitsma + * Copyright © 2007-2009 daniel g. siegel + * Copyright © 2008 Ryan Zeigler + * Copyright © 2010 Filippo Argiolas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include + +#ifdef HAVE_UDEV + #define G_UDEV_API_IS_SUBJECT_TO_CHANGE 1 + #include +#else + #include + #include + #include + #if USE_SYS_VIDEOIO_H > 0 + #include + #include + #elif defined (__sun) + #include + #include + #endif /* USE_SYS_VIDEOIO_H */ +#endif + +#include "cheese-camera-device-monitor.h" + +/** + * SECTION:cheese-camera-device-monitor + * @short_description: Simple object to enumerate v4l devices + * @include: cheese/cheese-camera-device-monitor.h + * + * #TpawCameraDeviceMonitor provides a basic interface for + * video4linux device enumeration and hotplugging. + * + * It uses either GUdev or some platform specific code to list video + * devices. It is also capable (right now in linux only, with the + * udev backend) to monitor device plugging and emit a + * TpawCameraDeviceMonitor::added or + * TpawCameraDeviceMonitor::removed signal when an event happens. + */ + +G_DEFINE_TYPE (TpawCameraDeviceMonitor, tpaw_camera_device_monitor, G_TYPE_OBJECT) + +#define TPAW_CAMERA_DEVICE_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + TPAW_TYPE_CAMERA_DEVICE_MONITOR, \ + TpawCameraDeviceMonitorPrivate)) + +#define TPAW_CAMERA_DEVICE_MONITOR_ERROR tpaw_camera_device_monitor_error_quark () + +#define DEBUG_FLAG EMPATHY_DEBUG_OTHER +#include "empathy-debug.h" + +enum TpawCameraDeviceMonitorError +{ + TPAW_CAMERA_DEVICE_MONITOR_ERROR_UNKNOWN, + TPAW_CAMERA_DEVICE_MONITOR_ERROR_ELEMENT_NOT_FOUND +}; + +typedef struct +{ +#ifdef HAVE_UDEV + GUdevClient *client; +#else + guint filler; +#endif /* HAVE_UDEV */ +} TpawCameraDeviceMonitorPrivate; + +enum +{ + ADDED, + REMOVED, + LAST_SIGNAL +}; + +static guint monitor_signals[LAST_SIGNAL]; + +#if 0 +GQuark +tpaw_camera_device_monitor_error_quark (void) +{ + return g_quark_from_static_string ("tpaw-camera-error-quark"); +} +#endif + +#ifdef HAVE_UDEV +static void +tpaw_camera_device_monitor_added (TpawCameraDeviceMonitor *monitor, + GUdevDevice *udevice) +{ + const char *device_file; + const char *product_name; + const char *vendor; + const char *product; + const char *bus; + gint vendor_id = 0; + gint product_id = 0; + gint v4l_version = 0; + + const gchar *devpath = g_udev_device_get_property (udevice, "DEVPATH"); + + DEBUG ("Checking udev device '%s'", devpath); + + bus = g_udev_device_get_property (udevice, "ID_BUS"); + if (g_strcmp0 (bus, "usb") == 0) + { + vendor = g_udev_device_get_property (udevice, "ID_VENDOR_ID"); + if (vendor != NULL) + vendor_id = g_ascii_strtoll (vendor, NULL, 16); + product = g_udev_device_get_property (udevice, "ID_MODEL_ID"); + if (product != NULL) + product_id = g_ascii_strtoll (product, NULL, 16); + if (vendor_id == 0 || product_id == 0) + { + DEBUG ("Error getting vendor and product id"); + } + else + { + DEBUG ("Found device %04x:%04x, getting capabilities...", vendor_id, product_id); + } + } + else + { + DEBUG ("Not an usb device, skipping vendor and model id retrieval"); + } + + device_file = g_udev_device_get_device_file (udevice); + if (device_file == NULL) + { + DEBUG ("Error getting V4L device"); + return; + } + + /* vbi devices support capture capability too, but cannot be used, + * so detect them by device name */ + if (strstr (device_file, "vbi")) + { + DEBUG ("Skipping vbi device: %s", device_file); + return; + } + + v4l_version = g_udev_device_get_property_as_int (udevice, "ID_V4L_VERSION"); + if (v4l_version == 2 || v4l_version == 1) + { + const char *caps; + + caps = g_udev_device_get_property (udevice, "ID_V4L_CAPABILITIES"); + if (caps == NULL || strstr (caps, ":capture:") == NULL) + { + DEBUG ("Device %s seems to not have the capture capability, (radio tuner?)" + "Removing it from device list.", device_file); + return; + } + product_name = g_udev_device_get_property (udevice, "ID_V4L_PRODUCT"); + } + else if (v4l_version == 0) + { + DEBUG ("Fix your udev installation to include v4l_id, ignoring %s", device_file); + return; + } + else + { + g_assert_not_reached (); + } + + g_signal_emit (monitor, monitor_signals[ADDED], 0, + devpath, + device_file, + product_name, + v4l_version); +} + +static void +tpaw_camera_device_monitor_removed (TpawCameraDeviceMonitor *monitor, + GUdevDevice *udevice) +{ + g_signal_emit (monitor, monitor_signals[REMOVED], 0, + g_udev_device_get_property (udevice, "DEVPATH")); +} + +static void +tpaw_camera_device_monitor_uevent_cb (GUdevClient *client, + const gchar *action, + GUdevDevice *udevice, + TpawCameraDeviceMonitor *monitor) +{ + if (g_str_equal (action, "remove")) + tpaw_camera_device_monitor_removed (monitor, udevice); + else if (g_str_equal (action, "add")) + tpaw_camera_device_monitor_added (monitor, udevice); +} + +/** + * tpaw_camera_device_monitor_coldplug: + * @monitor: a #TpawCameraDeviceMonitor object. + * + * Will actively look for plugged in cameras and emit + * ::added for those new cameras. + * This is only required when your program starts, so as to connect + * to those signals before they are emitted. + */ +void +tpaw_camera_device_monitor_coldplug (TpawCameraDeviceMonitor *monitor) +{ + TpawCameraDeviceMonitorPrivate *priv = TPAW_CAMERA_DEVICE_MONITOR_GET_PRIVATE (monitor); + GList *devices, *l; + gint i = 0; + + if (priv->client == NULL) + return; + + DEBUG ("Probing devices with udev..."); + + devices = g_udev_client_query_by_subsystem (priv->client, "video4linux"); + + /* Initialize camera structures */ + for (l = devices; l != NULL; l = l->next) + { + tpaw_camera_device_monitor_added (monitor, l->data); + g_object_unref (l->data); + i++; + } + g_list_free (devices); + + if (i == 0) DEBUG ("No device found"); +} + +#else /* HAVE_UDEV */ +void +tpaw_camera_device_monitor_coldplug (TpawCameraDeviceMonitor *monitor) +{ + #if 0 + TpawCameraDeviceMonitorPrivate *priv = TPAW_CAMERA_DEVICE_MONITOR_GET_PRIVATE (monitor); + struct v4l2_capability v2cap; + struct video_capability v1cap; + int fd, ok; + + if ((fd = open (device_path, O_RDONLY | O_NONBLOCK)) < 0) + { + g_warning ("Failed to open %s: %s", device_path, strerror (errno)); + return; + } + ok = ioctl (fd, VIDIOC_QUERYCAP, &v2cap); + if (ok < 0) + { + ok = ioctl (fd, VIDIOCGCAP, &v1cap); + if (ok < 0) + { + g_warning ("Error while probing v4l capabilities for %s: %s", + device_path, strerror (errno)); + close (fd); + return; + } + g_print ("Detected v4l device: %s\n", v1cap.name); + g_print ("Device type: %d\n", v1cap.type); + gstreamer_src = "v4lsrc"; + product_name = v1cap.name; + } + else + { + guint cap = v2cap.capabilities; + g_print ("Detected v4l2 device: %s\n", v2cap.card); + g_print ("Driver: %s, version: %d\n", v2cap.driver, v2cap.version); + + /* g_print ("Bus info: %s\n", v2cap.bus_info); */ /* Doesn't seem anything useful */ + g_print ("Capabilities: 0x%08X\n", v2cap.capabilities); + if (!(cap & V4L2_CAP_VIDEO_CAPTURE)) + { + g_print ("Device %s seems to not have the capture capability, (radio tuner?)\n" + "Removing it from device list.\n", device_path); + close (fd); + return; + } + gstreamer_src = "v4l2src"; + product_name = (char *) v2cap.card; + } + close (fd); + + GList *devices, *l; + + g_print ("Probing devices with udev...\n"); + + if (priv->client == NULL) + return; + + devices = g_udev_client_query_by_subsystem (priv->client, "video4linux"); + + /* Initialize camera structures */ + for (l = devices; l != NULL; l = l->next) + { + tpaw_camera_device_monitor_added (monitor, l->data); + g_object_unref (l->data); + } + g_list_free (devices); + #endif +} + +#endif /* HAVE_UDEV */ + +static void +tpaw_camera_device_monitor_finalize (GObject *object) +{ +#ifdef HAVE_UDEV + TpawCameraDeviceMonitor *monitor = TPAW_CAMERA_DEVICE_MONITOR (object); + TpawCameraDeviceMonitorPrivate *priv = TPAW_CAMERA_DEVICE_MONITOR_GET_PRIVATE (monitor); + + if (priv->client != NULL) + { + g_object_unref (priv->client); + priv->client = NULL; + } +#endif /* HAVE_UDEV */ + G_OBJECT_CLASS (tpaw_camera_device_monitor_parent_class)->finalize (object); +} + +static void +tpaw_camera_device_monitor_class_init (TpawCameraDeviceMonitorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = tpaw_camera_device_monitor_finalize; + + /** + * TpawCameraDeviceMonitor::added: + * @device: A private object representing the newly added camera. + * @id: Device unique identifier. + * @device: Device file name (e.g. /dev/video2). + * @product_name: Device product name (human readable, intended to be displayed in a UI). + * @api_version: Supported video4linux API: 1 for v4l, 2 for v4l2. + * + * The ::added signal is emitted when a camera is added, or on start-up + * after #tpaw_camera_device_monitor_colplug is called. + **/ + monitor_signals[ADDED] = g_signal_new ("added", G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (TpawCameraDeviceMonitorClass, added), + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); + + /** + * TpawCameraDeviceMonitor::removed: + * @device: A private object representing the newly added camera + * @id: Device unique identifier. + * + * The ::removed signal is emitted when a camera is un-plugged, or + * disabled on the system. + **/ + monitor_signals[REMOVED] = g_signal_new ("removed", G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (TpawCameraDeviceMonitorClass, removed), + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 1, G_TYPE_STRING); + + g_type_class_add_private (klass, sizeof (TpawCameraDeviceMonitorPrivate)); +} + +static void +tpaw_camera_device_monitor_init (TpawCameraDeviceMonitor *monitor) +{ +#ifdef HAVE_UDEV + TpawCameraDeviceMonitorPrivate *priv = TPAW_CAMERA_DEVICE_MONITOR_GET_PRIVATE (monitor); + const gchar *const subsystems[] = {"video4linux", NULL}; + + priv->client = g_udev_client_new (subsystems); + g_signal_connect (G_OBJECT (priv->client), "uevent", + G_CALLBACK (tpaw_camera_device_monitor_uevent_cb), monitor); +#endif /* HAVE_UDEV */ +} + +/** + * tpaw_camera_device_monitor_new: + * + * Returns a new #TpawCameraDeviceMonitor object. + * + * Return value: a new #TpawCameraDeviceMonitor object. + **/ +TpawCameraDeviceMonitor * +tpaw_camera_device_monitor_new (void) +{ + return g_object_new (TPAW_TYPE_CAMERA_DEVICE_MONITOR, NULL); +} + +/* + * vim: sw=2 ts=8 cindent noai bs=2 + */ diff --git a/tp-account-widgets/cheese-camera-device-monitor.h b/tp-account-widgets/cheese-camera-device-monitor.h new file mode 100644 index 000000000..353440226 --- /dev/null +++ b/tp-account-widgets/cheese-camera-device-monitor.h @@ -0,0 +1,67 @@ +/* This file is a copy of cheese-camera-device-monitor.h from Tpaw. We + * just renamespaced it to avoid conflicts when linking on libcheese. */ +/* + * Copyright © 2007,2008 Jaap Haitsma + * Copyright © 2007-2009 daniel g. siegel + * Copyright © 2008 Ryan zeigler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef __TPAW_CAMERA_DEVICE_MONITOR_H__ +#define __TPAW_CAMERA_DEVICE_MONITOR_H__ + +#include + +G_BEGIN_DECLS + +#define TPAW_TYPE_CAMERA_DEVICE_MONITOR (tpaw_camera_device_monitor_get_type ()) +#define TPAW_CAMERA_DEVICE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TPAW_TYPE_CAMERA_DEVICE_MONITOR, \ + TpawCameraDeviceMonitor)) +#define TPAW_CAMERA_DEVICE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TPAW_TYPE_CAMERA_DEVICE_MONITOR, \ + TpawCameraDeviceMonitorClass)) +#define TPAW_IS_CAMERA_DEVICE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TPAW_TYPE_CAMERA_DEVICE_MONITOR)) +#define TPAW_IS_CAMERA_DEVICE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TPAW_TYPE_CAMERA_DEVICE_MONITOR)) +#define TPAW_CAMERA_DEVICE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TPAW_TYPE_CAMERA_DEVICE_MONITOR, \ + TpawCameraDeviceMonitorClass)) + +typedef struct _TpawCameraDeviceMonitorClass TpawCameraDeviceMonitorClass; +typedef struct _TpawCameraDeviceMonitor TpawCameraDeviceMonitor; + +struct _TpawCameraDeviceMonitor +{ + GObject parent; +}; + +struct _TpawCameraDeviceMonitorClass +{ + GObjectClass parent_class; + + void (*added)(TpawCameraDeviceMonitor *camera, + const char *id, + const char *device_file, + const char *product_name, + int api_version); + void (*removed)(TpawCameraDeviceMonitor *camera, const char *id); +}; + +GType tpaw_camera_device_monitor_get_type (void) G_GNUC_CONST; +TpawCameraDeviceMonitor *tpaw_camera_device_monitor_new (void); +void tpaw_camera_device_monitor_coldplug (TpawCameraDeviceMonitor *monitor); + +G_END_DECLS + +#endif /* __TPAW_CAMERA_DEVICE_MONITOR_H__ */ -- cgit v1.2.3