243 lines
8.4 KiB
Diff
243 lines
8.4 KiB
Diff
diff -up cheese-2.23.91/src/cheese-webcam.c.orig cheese-2.23.91/src/cheese-webcam.c
|
|
--- cheese-2.23.91/src/cheese-webcam.c.orig 2008-09-01 20:47:10.000000000 +0200
|
|
+++ cheese-2.23.91/src/cheese-webcam.c 2008-09-03 20:27:25.000000000 +0200
|
|
@@ -33,6 +33,11 @@
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
#include <X11/Xlib.h>
|
|
#include <libhal.h>
|
|
+/* for ioctl query */
|
|
+#include <fcntl.h>
|
|
+#include <unistd.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include <linux/videodev.h>
|
|
|
|
#include "cheese-webcam.h"
|
|
#include "cheese-flash.h"
|
|
@@ -235,16 +240,13 @@ cheese_webcam_get_video_devices_from_hal
|
|
{
|
|
CheeseWebcamPrivate *priv = CHEESE_WEBCAM_GET_PRIVATE (webcam);
|
|
|
|
- int i;
|
|
- int num_udis;
|
|
- int num_devices; /* Devices we actually create formats for; can either be the
|
|
- * number of webcams detected, or 1 if none were. The one
|
|
- * refers to a fake device so that resolution changing still
|
|
- * works even if the computer doesn't have a webcam. */
|
|
+ int i, fd, ok;
|
|
+ int num_udis = 0;
|
|
char **udis;
|
|
DBusError error;
|
|
LibHalContext *hal_ctx;
|
|
|
|
+ priv->num_webcam_devices = 0;
|
|
|
|
dbus_error_init (&error);
|
|
hal_ctx = libhal_ctx_new ();
|
|
@@ -252,14 +254,14 @@ cheese_webcam_get_video_devices_from_hal
|
|
{
|
|
g_error ("error: libhal_ctx_new");
|
|
dbus_error_free (&error);
|
|
- return;
|
|
+ goto fallback;
|
|
}
|
|
|
|
if (!libhal_ctx_set_dbus_connection (hal_ctx, dbus_bus_get (DBUS_BUS_SYSTEM, &error)))
|
|
{
|
|
g_error ("error: libhal_ctx_set_dbus_connection: %s: %s", error.name, error.message);
|
|
dbus_error_free (&error);
|
|
- return;
|
|
+ goto fallback;
|
|
}
|
|
|
|
if (!libhal_ctx_init (hal_ctx, &error))
|
|
@@ -271,53 +273,113 @@ cheese_webcam_get_video_devices_from_hal
|
|
}
|
|
g_error ("Could not initialise connection to hald.\n"
|
|
"Normally this means the HAL daemon (hald) is not running or not ready");
|
|
- return;
|
|
+ goto fallback;
|
|
}
|
|
|
|
udis = libhal_find_device_by_capability (hal_ctx, "video4linux", &num_udis, &error);
|
|
|
|
if (dbus_error_is_set (&error))
|
|
{
|
|
- g_error ("error: %s: %s\n", error.name, error.message);
|
|
+ g_error ("error: libhal_find_device_by_capability: %s: %s\n", error.name, error.message);
|
|
dbus_error_free (&error);
|
|
- return;
|
|
+ goto fallback;
|
|
}
|
|
|
|
/* Initialize webcam structures */
|
|
+ priv->webcam_devices = g_new0 (CheeseWebcamDevice, num_udis);
|
|
|
|
- if (num_udis > 0)
|
|
- priv->num_webcam_devices = num_devices = num_udis;
|
|
- else
|
|
- {
|
|
- num_devices = 1;
|
|
- priv->num_webcam_devices = num_udis; /* We don't have any real cameras--
|
|
- * this is important when we create
|
|
- * the pipeline. */
|
|
- }
|
|
-
|
|
- priv->webcam_devices = g_new0 (CheeseWebcamDevice, num_devices);
|
|
- for (i = 0; i < num_devices; i++)
|
|
- {
|
|
- priv->webcam_devices[i].num_video_formats = 0;
|
|
- priv->webcam_devices[i].video_formats = g_array_new (FALSE, FALSE, sizeof (CheeseVideoFormat));
|
|
- priv->webcam_devices[i].hal_udi = g_strdup (udis[i]);
|
|
- }
|
|
-
|
|
- for (i = 0; i < priv->num_webcam_devices; i++)
|
|
+ for (i = 0; i < num_udis; i++)
|
|
{
|
|
char *device;
|
|
+ char *gstreamer_src, *product_name;
|
|
+ struct v4l2_capability v2cap;
|
|
+ struct video_capability v1cap;
|
|
|
|
device = libhal_device_get_property_string (hal_ctx, udis[i], "video4linux.device", &error);
|
|
- if (dbus_error_is_set (&error))
|
|
+ if (dbus_error_is_set (&error))
|
|
{
|
|
- g_error ("error: %s: %s\n", error.name, error.message);
|
|
+ g_error ("error geting device for %s: %s: %s\n", udis[i], error.name, error.message);
|
|
dbus_error_free (&error);
|
|
- return;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* vbi devices support capture capability too, but cannot be used,
|
|
+ so detect them by device name */
|
|
+ if (strstr(device, "vbi"))
|
|
+ {
|
|
+ g_print ("Skipping vbi device: %s\n", device);
|
|
+ libhal_free_string (device);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if ((fd = open(device, O_RDONLY | O_NONBLOCK)) < 0)
|
|
+ {
|
|
+ g_error ("Failed to open %s: %s\n", device, strerror(errno));
|
|
+ libhal_free_string (device);
|
|
+ continue;
|
|
+ }
|
|
+ ok = ioctl (fd, VIDIOC_QUERYCAP, &v2cap);
|
|
+ if (ok < 0) {
|
|
+ ok = ioctl (fd, VIDIOCGCAP, &v1cap);
|
|
+ if (ok < 0) {
|
|
+ g_error ("Error while probing v4l capabilities for %s: %s\n",
|
|
+ device, strerror (errno));
|
|
+ libhal_free_string (device);
|
|
+ close(fd);
|
|
+ continue;
|
|
+ }
|
|
+ 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);
|
|
+ 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);
|
|
+ libhal_free_string (device);
|
|
+ close(fd);
|
|
+ continue;
|
|
+ }
|
|
+ gstreamer_src = "v4l2src";
|
|
+ product_name = (char *)v2cap.card;
|
|
}
|
|
- priv->webcam_devices[i].video_device = g_strdup (device);
|
|
+
|
|
+ priv->webcam_devices[priv->num_webcam_devices].hal_udi = g_strdup (udis[i]);
|
|
+ priv->webcam_devices[priv->num_webcam_devices].video_device = g_strdup (device);
|
|
+ priv->webcam_devices[priv->num_webcam_devices].gstreamer_src = g_strdup (gstreamer_src);
|
|
+ priv->webcam_devices[priv->num_webcam_devices].product_name = g_strdup (product_name);
|
|
+ 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->num_webcam_devices++;
|
|
+
|
|
libhal_free_string (device);
|
|
+ close(fd);
|
|
}
|
|
libhal_free_string_array (udis);
|
|
+
|
|
+ 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. */
|
|
+fallback:
|
|
+ if (num_udis == 0)
|
|
+ {
|
|
+ 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");
|
|
+ }
|
|
}
|
|
|
|
static void
|
|
@@ -479,19 +541,11 @@ cheese_webcam_get_webcam_device_data (Ch
|
|
GstStateChangeReturn ret;
|
|
GstMessage *msg;
|
|
GstBus *bus;
|
|
- gboolean pipeline_works = FALSE;
|
|
int i, j;
|
|
|
|
- static const char *GSTREAMER_VIDEO_SOURCES[] = {
|
|
- "v4l2src",
|
|
- "v4lsrc"
|
|
- };
|
|
-
|
|
- i = 0;
|
|
- while (!pipeline_works && (i < G_N_ELEMENTS (GSTREAMER_VIDEO_SOURCES)))
|
|
{
|
|
pipeline_desc = g_strdup_printf ("%s name=source device=%s ! fakesink",
|
|
- GSTREAMER_VIDEO_SOURCES[i],
|
|
+ webcam_device->gstreamer_src,
|
|
webcam_device->video_device);
|
|
err = NULL;
|
|
pipeline = gst_parse_launch (pipeline_desc, &err);
|
|
@@ -513,10 +567,8 @@ cheese_webcam_get_webcam_device_data (Ch
|
|
char *name;
|
|
GstCaps *caps;
|
|
|
|
- pipeline_works = TRUE;
|
|
gst_element_set_state (pipeline, GST_STATE_PAUSED);
|
|
|
|
- webcam_device->gstreamer_src = g_strdup (GSTREAMER_VIDEO_SOURCES[i]);
|
|
src = gst_bin_get_by_name (GST_BIN (pipeline), "source");
|
|
|
|
g_object_get (G_OBJECT (src), "device-name", &name, NULL);
|
|
@@ -524,7 +576,6 @@ cheese_webcam_get_webcam_device_data (Ch
|
|
name = "Unknown";
|
|
|
|
g_print ("Detected webcam: %s\n", name);
|
|
- webcam_device->product_name = g_strdup (name);
|
|
pad = gst_element_get_pad (src, "src");
|
|
caps = gst_pad_get_caps (pad);
|
|
gst_object_unref (pad);
|
|
@@ -538,8 +589,8 @@ cheese_webcam_get_webcam_device_data (Ch
|
|
g_error_free (err);
|
|
|
|
g_free (pipeline_desc);
|
|
- i++;
|
|
}
|
|
+
|
|
g_print ("device: %s\n", webcam_device->video_device);
|
|
for (i = 0; i < webcam_device->num_video_formats; i++)
|
|
{
|