$OpenBSD: patch-src_cheese-webcam_c,v 1.7 2009/11/09 09:56:46 jasper Exp $

Unbreak cheese on OpenBSD with uvideo(4).

--- src/cheese-webcam.c.orig	Mon Nov  9 10:45:12 2009
+++ src/cheese-webcam.c	Mon Nov  9 10:53:12 2009
@@ -31,13 +31,19 @@
 #include <gst/gst.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <X11/Xlib.h>
+#ifndef __OpenBSD__
 #include <libhal.h>
+#endif /* !__OpenBSD__ */
 
 /* for ioctl query */
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
+#ifdef __OpenBSD__
+#include <sys/videoio.h>
+#else
 #include <linux/videodev.h>
+#endif /* __OpenBSD__ */
 
 #include "cheese-webcam.h"
 
@@ -276,11 +282,117 @@ cheese_webcam_bus_message_cb (GstBus *bus, GstMessage 
   }
 }
 
+#ifdef __OpenBSD__
 static void
 cheese_webcam_get_video_devices_from_hal (CheeseWebcam *webcam)
 {
   CheeseWebcamPrivate *priv = CHEESE_WEBCAM_GET_PRIVATE (webcam);
 
+  int            i, fd, ok, max_devs = 20;
+  struct dev_info {
+    int   node;
+    char  *pname;
+  }dev_list[max_devs];
+
+  priv->num_webcam_devices = 0;
+
+  g_print ("Probing devices with HAL...\n");
+
+  for (i = 0; i < max_devs; i++)
+   {
+    char                   *device;
+    struct stat s;
+    char                   *gstreamer_src, *product_name;
+    struct v4l2_capability  v2cap;
+
+    dev_list[i].node = -1;
+    device = g_strdup_printf("%s%d", "/dev/video", i);
+    if (lstat(device, &s) != 0)
+      continue;
+
+    if ((fd = open (device, O_RDONLY | O_NONBLOCK)) < 0)
+    {
+      g_warning ("Failed to open %s: %s", device, strerror (errno));
+      free (device);
+      continue;
+    }
+    ok = ioctl (fd, VIDIOC_QUERYCAP, &v2cap);
+    if (ok < 0)
+    {
+      g_warning ("Failed to query the capture capability of %s: %s", device, strerror (errno));
+      free (device);
+      continue;
+    }
+    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);
+        free (device);
+        close (fd);
+        continue;
+      }
+      product_name  = (char *) v2cap.card;
+    }
+
+    g_print ("\n");
+
+    dev_list[i].node = i;
+    dev_list[i].pname = product_name;
+    priv->num_webcam_devices++;
+
+    free (device);
+    if (fd >= 0)
+      close (fd);
+  }
+
+  /* Initialize webcam structures */
+  priv->webcam_devices = g_new0 (CheeseWebcamDevice, priv->num_webcam_devices);
+  priv->num_webcam_devices = 0;
+
+  for (i = 0; i < max_devs; i++)
+  {
+    char *device;
+    if (dev_list[i].node < 0)
+      continue;
+    device = g_strdup_printf("%s%d", "/dev/video", i);
+    priv->webcam_devices[priv->num_webcam_devices].hal_udi           = g_strdup (device);
+    priv->webcam_devices[priv->num_webcam_devices].video_device      = g_strdup (device);
+    priv->webcam_devices[priv->num_webcam_devices].gstreamer_src     = g_strdup ("v4l2src");
+    priv->webcam_devices[priv->num_webcam_devices].product_name      = g_strdup (dev_list[i].pname);
+    priv->webcam_devices[priv->num_webcam_devices].num_video_formats = 0;
+    priv->webcam_devices[priv->num_webcam_devices].video_formats     =
+      g_array_new (FALSE, FALSE, sizeof (CheeseVideoFormat));
+    priv->webcam_devices[priv->num_webcam_devices].supported_resolutions =
+      g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+    priv->num_webcam_devices++;
+
+  }
+
+  if (priv->num_webcam_devices == 0)
+  {
+    /* Create a fake device so that resolution changing stil works even if the
+     * computer doesn't have a webcam. */
+    priv->webcam_devices = g_new0 (CheeseWebcamDevice, 1);
+    priv->webcam_devices[0].num_video_formats = 0;
+    priv->webcam_devices[0].video_formats     =
+      g_array_new (FALSE, FALSE, sizeof (CheeseVideoFormat));
+    priv->webcam_devices[0].hal_udi = g_strdup ("cheese_fake_videodevice");
+  }
+}
+#else
+static void
+cheese_webcam_get_video_devices_from_hal (CheeseWebcam *webcam)
+{
+  CheeseWebcamPrivate *priv = CHEESE_WEBCAM_GET_PRIVATE (webcam);
+
   int            i, fd, ok;
   int            num_udis = 0;
   char         **udis;
@@ -470,6 +582,7 @@ fallback:
     priv->webcam_devices[0].hal_udi = g_strdup ("cheese_fake_videodevice");
   }
 }
+#endif /* __OpenBSD__ */
 
 static void
 cheese_webcam_get_supported_framerates (CheeseVideoFormat *video_format, GstStructure *structure)
@@ -712,7 +825,8 @@ cheese_webcam_get_webcam_device_data (CheeseWebcam    
     if ((pipeline != NULL) && (err == NULL))
     {
       /* Start the pipeline and wait for max. 10 seconds for it to start up */
-      gst_element_set_state (pipeline, GST_STATE_PLAYING);
+      /* XXX Disable this to make it startup instantly */
+      /* gst_element_set_state (pipeline, GST_STATE_PLAYING); */
       ret = gst_element_get_state (pipeline, NULL, NULL, 10 * GST_SECOND);
 
       /* Check if any error messages were posted on the bus */
