$NetBSD: patch-ab,v 1.8 2009/05/20 15:37:38 wiz Exp $

http://bugzilla.gnome.org/show_bug.cgi?id=583469

--- src/cheese-webcam.c.orig	2009-05-18 20:46:03.000000000 +0000
+++ src/cheese-webcam.c
@@ -31,13 +31,26 @@
 #include <gst/gst.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <X11/Xlib.h>
+
+#if HAVE_HAL
 #include <libhal.h>
+#endif
 
-/* for ioctl query */
+#include <sys/ioctl.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <sys/ioctl.h>
+
+#if USE_SYS_VIDEOIO_H > 0
+#include <sys/types.h>
+#include <sys/videoio.h>
+#elif defined(__sun)
+#include <sys/types.h>
+#include <sys/videodev2.h>
+#elif defined(__linux__)
 #include <linux/videodev.h>
+#else
+#define NO_VIDEO_SUPPORT
+#endif
 
 #include "cheese-webcam.h"
 
@@ -241,6 +254,7 @@ cheese_webcam_bus_message_cb (GstBus *bu
   }
 }
 
+#if HAVE_HAL
 static void
 cheese_webcam_get_video_devices_from_hal (CheeseWebcam *webcam)
 {
@@ -302,8 +316,12 @@ cheese_webcam_get_video_devices_from_hal
     char                   *parent_udi = NULL;
     char                   *subsystem = NULL;
     char                   *gstreamer_src, *product_name;
+#ifndef NO_VIDEO_SUPPORT
     struct v4l2_capability  v2cap;
+#endif
+#ifdef VIDIOCGCAP
     struct video_capability v1cap;
+#endif
     gint vendor_id = 0;
     gint product_id = 0;
     gchar *property_name = NULL;
@@ -317,15 +335,17 @@ cheese_webcam_get_video_devices_from_hal
 
     if (parent_udi != NULL) {
       subsystem = libhal_device_get_property_string (hal_ctx, parent_udi, "info.subsystem", NULL);
-      if (subsystem == NULL) continue;
-      property_name = g_strjoin (".", subsystem, "vendor_id", NULL);
-      vendor_id = libhal_device_get_property_int (hal_ctx, parent_udi, property_name , &error);
-      if (dbus_error_is_set (&error)) {
-        g_warning ("error getting vendor id: %s: %s", error.name, error.message);
-        dbus_error_free (&error);
+      if (subsystem == NULL) {
+	vendor_id = g_strdup("{No vendor ID}");
+      } else {
+        property_name = g_strjoin (".", subsystem, "vendor_id", NULL);
+        vendor_id = libhal_device_get_property_int (hal_ctx, parent_udi, property_name , &error);
+        if (dbus_error_is_set (&error)) {
+          g_warning ("error getting vendor id: %s: %s", error.name, error.message);
+          dbus_error_free (&error);
+        }
+        g_free (property_name);
       }
-      g_free (property_name);
-
       property_name = g_strjoin (".", subsystem, "product_id", NULL);
       product_id = libhal_device_get_property_int (hal_ctx, parent_udi, property_name, &error);
       if (dbus_error_is_set (&error)) {
@@ -362,9 +382,14 @@ cheese_webcam_get_video_devices_from_hal
       libhal_free_string (device);
       continue;
     }
+#ifdef VIDIOC_QUERYCAP
     ok = ioctl (fd, VIDIOC_QUERYCAP, &v2cap);
+#else
+    ok = -1;
+#endif
     if (ok < 0)
     {
+#ifdef VIDIOCGCAP
       ok = ioctl (fd, VIDIOCGCAP, &v1cap);
       if (ok < 0)
       {
@@ -378,14 +403,22 @@ cheese_webcam_get_video_devices_from_hal
       g_print ("Device type: %d\n", v1cap.type);
       gstreamer_src = "v4lsrc";
       product_name  = v1cap.name;
+#else
+      g_error ("Error while probing v4l2 capabilities for %s: %s\n",
+	       device, strerror (errno));
+      libhal_free_string (device);
+      close (fd);
+      continue;
+#endif
     }
     else
     {
+#ifndef NO_VIDEO_SUPPORT
       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);
+      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"
@@ -396,6 +429,10 @@ cheese_webcam_get_video_devices_from_hal
       }
       gstreamer_src = "v4l2src";
       product_name  = (char *) v2cap.card;
+#else /* NO_VIDEO_SUPPORT */
+      gstreamer_src = "v4l2src";
+      product_name = "Webcam";
+#endif
     }
 
     g_print ("\n");
@@ -431,6 +468,55 @@ fallback:
     priv->webcam_devices[0].hal_udi = g_strdup ("cheese_fake_videodevice");
   }
 }
+#else
+static void
+cheese_webcam_get_video_devices_from_probe (CheeseWebcam *webcam)
+{
+  CheeseWebcamPrivate* priv = CHEESE_WEBCAM_GET_PRIVATE (webcam);
+  struct v4l2_capability caps;
+  gchar videodev[] = "/dev/video?";
+  guint16 cammask = 0;
+  int i, ncams = 0, fd, ret, cur = 0;
+
+  for (i = 0; i < 9; i++)
+  {
+    videodev[strlen(videodev) - 1] = '0' + i;
+    fd = open(videodev, O_RDONLY);
+    if (fd == -1)
+      continue;
+    ret = ioctl(fd, VIDIOC_QUERYCAP, &caps);
+    close(fd);
+    if (ret)
+    {
+      continue;
+    }
+    g_message("Found video device: %s\n", caps.card);
+    cammask |= (1 << i);
+    ++ncams;
+  }
+
+  priv->num_webcam_devices = ncams;
+  if (ncams == 0)
+    return;
+  priv->webcam_devices = g_new0 (CheeseWebcamDevice, ncams);
+  for (i = 0; i < ncams; i++)
+  {
+    priv->webcam_devices[i].num_video_formats = 0;
+    priv->webcam_devices[i].video_formats = g_array_new (FALSE, FALSE, sizeof (CheeseVideoFormat));
+  }
+
+  for (i = 0; i < 9; i++)
+  {
+    if (cammask & (1 << i))
+    {
+      videodev[strlen(videodev) - 1] = '0' + i;
+      priv->webcam_devices[i].video_device = g_strdup (videodev);
+      ++cur;
+    }
+  }
+}
+#endif /* !HAVE_HAL */
+
 
 static void
 cheese_webcam_get_supported_framerates (CheeseVideoFormat *video_format, GstStructure *structure)
@@ -736,7 +822,11 @@ cheese_webcam_detect_webcam_devices (Che
 
   int i;
 
+#if HAVE_HAL
   cheese_webcam_get_video_devices_from_hal (webcam);
+#else
+  cheese_webcam_get_video_devices_from_probe (webcam);
+#endif
 
   g_print ("Probing supported video formats...\n");
   for (i = 0; i < priv->num_webcam_devices; i++)
