[cheese] Add hotplug support to preferences dialog
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cheese] Add hotplug support to preferences dialog
- Date: Fri, 4 Nov 2011 14:48:47 +0000 (UTC)
commit 884e34e97a13e049fc538a3b030b9bce38aa8d63
Author: Patricia Santana Cruz <patriciasantanacruz gmail com>
Date: Fri Nov 4 13:54:38 2011 +0100
Add hotplug support to preferences dialog
Adding and removing camera devices in the CheeseCamera is now propagated
to the preferences dialog UI. Partially fixes bug 603612.
libcheese/cheese-camera.c | 29 +++++++++-
src/cheese-preferences.vala | 126 +++++++++++++++++++++++++++++++++++++------
src/vapi/cheese-common.vapi | 2 +
3 files changed, 138 insertions(+), 19 deletions(-)
---
diff --git a/libcheese/cheese-camera.c b/libcheese/cheese-camera.c
index bcb66a1..396b826 100644
--- a/libcheese/cheese-camera.c
+++ b/libcheese/cheese-camera.c
@@ -101,7 +101,7 @@ struct _CheeseCameraPrivate
gboolean pipeline_is_playing;
gchar *photo_filename;
- gint num_camera_devices;
+ guint num_camera_devices;
gchar *device_name;
/* an array of CheeseCameraDevices */
@@ -122,6 +122,8 @@ enum
PROP_VIDEO_TEXTURE,
PROP_DEVICE_NAME,
PROP_FORMAT,
+ PROP_NUM_CAMERA_DEVICES,
+ PROP_LAST
};
enum
@@ -134,6 +136,7 @@ enum
};
static guint camera_signals[LAST_SIGNAL];
+static GParamSpec *properties[PROP_LAST];
GST_DEBUG_CATEGORY (cheese_camera_cat);
#define GST_CAT_DEFAULT cheese_camera_cat
@@ -275,6 +278,8 @@ cheese_camera_add_device (CheeseCameraDeviceMonitor *monitor,
g_ptr_array_add (priv->camera_devices, device);
priv->num_camera_devices++;
+
+ g_object_notify_by_pspec (G_OBJECT (camera), properties[PROP_NUM_CAMERA_DEVICES]);
}
/*
@@ -305,6 +310,7 @@ cheese_camera_remove_device (CheeseCameraDeviceMonitor *monitor,
{
g_ptr_array_remove (priv->camera_devices, (gpointer) indexDevice);
priv->num_camera_devices--;
+ g_object_notify_by_pspec (G_OBJECT (camera), properties[PROP_NUM_CAMERA_DEVICES]);
break;
}
}
@@ -1097,6 +1103,9 @@ cheese_camera_get_property (GObject *object, guint prop_id, GValue *value,
case PROP_FORMAT:
g_value_set_boxed (value, priv->current_format);
break;
+ case PROP_NUM_CAMERA_DEVICES:
+ g_value_set_uint (value, priv->num_camera_devices);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1218,7 +1227,7 @@ cheese_camera_class_init (CheeseCameraClass *klass)
g_object_class_install_property (object_class, PROP_DEVICE_NAME,
g_param_spec_string ("device-name",
"Device name",
- "The path to the device node for the video capture device.",
+ "The path to the device node for the video capture device",
"",
G_PARAM_READWRITE));
@@ -1234,6 +1243,22 @@ cheese_camera_class_init (CheeseCameraClass *klass)
CHEESE_TYPE_VIDEO_FORMAT,
G_PARAM_READWRITE));
+ /**
+ * CheeseCamera:num-camera-devices:
+ *
+ * The currently number of camera devices available for being used.
+ */
+
+ properties[PROP_NUM_CAMERA_DEVICES] = g_param_spec_uint ("num-camera-devices",
+ "Number of camera devices",
+ "The currently number of camera devices available on the system",
+ 0,
+ G_MAXUINT8,
+ 0,
+ G_PARAM_READABLE);
+
+ g_object_class_install_property (object_class, PROP_NUM_CAMERA_DEVICES, properties[PROP_NUM_CAMERA_DEVICES]);
+
g_type_class_add_private (klass, sizeof (CheeseCameraPrivate));
}
diff --git a/src/cheese-preferences.vala b/src/cheese-preferences.vala
index df7b07e..fe3604f 100644
--- a/src/cheese-preferences.vala
+++ b/src/cheese-preferences.vala
@@ -33,6 +33,8 @@ public class Cheese.PreferencesDialog : GLib.Object
private Gtk.ComboBox video_resolution_combo;
private Gtk.ComboBox source_combo;
+ private Gtk.ListStore camera_model;
+
private Gtk.Adjustment brightness_adjustment;
private Gtk.Adjustment contrast_adjustment;
private Gtk.Adjustment hue_adjustment;
@@ -54,6 +56,7 @@ public class Cheese.PreferencesDialog : GLib.Object
public PreferencesDialog (Cheese.Camera camera, GLib.Settings settings)
{
this.camera = camera;
+
this.settings = settings;
Gtk.Builder builder = new Gtk.Builder ();
@@ -104,6 +107,7 @@ public class Cheese.PreferencesDialog : GLib.Object
* Stops a bunch of unnecessary signals from being fired
*/
builder.connect_signals (this);
+ camera.notify["num-camera-devices"].connect(this.on_camera_update_num_camera_devices);
}
private void setup_combo_box_models ()
@@ -122,27 +126,14 @@ public class Cheese.PreferencesDialog : GLib.Object
private void initialize_camera_devices ()
{
- Cheese.CameraDevice dev;
- unowned GLib.PtrArray devices = camera.get_camera_devices ();
- ListStore camera_model = new ListStore (2, typeof (string), typeof (Cheese.CameraDevice));
+ unowned GLib.PtrArray devices = camera.get_camera_devices ();
+ camera_model = new ListStore (2, typeof (string), typeof (Cheese.CameraDevice));
source_combo.model = camera_model;
if (devices.len <= 1)
source_combo.sensitive = false;
- for (int i = 0; i < devices.len; i++)
- {
- TreeIter iter;
- dev = (Cheese.CameraDevice) devices.index (i);
- camera_model.append (out iter);
- camera_model.set (iter,
- 0, dev.get_name () + " (" + dev.get_device_file () + " )",
- 1, dev);
- if (camera.get_selected_device ().get_device_file () == dev.get_device_file ())
- {
- source_combo.set_active_iter (iter);
- }
- }
+ devices.foreach(add_camera_device);
settings.set_string ("camera", camera.get_selected_device ().get_device_file ());
setup_resolutions_for_device (camera.get_selected_device ());
@@ -209,8 +200,10 @@ public class Cheese.PreferencesDialog : GLib.Object
[CCode (instance_pos = -1)]
public void on_source_change (Gtk.ComboBox combo)
{
- TreeIter iter;
+ // TODO: Handle going from 1 to 0 devices, cleanly!
+ return_if_fail (camera.num_camera_devices > 0);
+ TreeIter iter;
Cheese.CameraDevice dev;
combo.get_active_iter (out iter);
@@ -333,6 +326,105 @@ public class Cheese.PreferencesDialog : GLib.Object
settings.set_double ("saturation", adjustment.value);
}
+ // A camera device was added/removed.
+ public void on_camera_update_num_camera_devices ()
+ {
+ unowned GLib.PtrArray devices = camera.get_camera_devices ();
+ Cheese.CameraDevice dev;
+
+ // Add (if) / Remove (else) a camera device.
+ if (devices.len > camera_model.iter_n_children (null))
+ {
+ dev = (Cheese.CameraDevice) devices.index (devices.len - 1);
+ add_camera_device(dev);
+ }
+ else
+ {
+ // First camera device in the combobox.
+ TreeIter iter;
+ camera_model.get_iter_first (out iter);
+
+ // Combobox active element.
+ TreeIter active_iter;
+ Cheese.CameraDevice active_device;
+ source_combo.get_active_iter (out active_iter);
+ camera_model.get (active_iter, 1, out active_device, -1);
+
+ // Find which device was removed.
+ bool device_removed = false;
+ devices.foreach ((device) =>
+ {
+ var old_device = (Cheese.CameraDevice) device;
+ Cheese.CameraDevice new_device;
+ camera_model.get (iter, 1, out new_device, -1);
+
+ // Found the device that was removed.
+ if (strcmp (old_device.device_file, new_device.device_file) != 0)
+ {
+ remove_camera_device (iter, new_device, active_device);
+ device_removed = true;
+ // Remember, this is from the anonymous function!
+ return;
+ }
+ camera_model.iter_next (ref iter);
+ });
+
+ // Special case: the last device on the list was removed.
+ if (!device_removed)
+ {
+ Cheese.CameraDevice old_device;
+ camera_model.get (iter, 1, out old_device, -1);
+ remove_camera_device (iter, old_device, active_device);
+ }
+ }
+
+ settings.set_string ("camera", camera.get_selected_device ().get_device_file ());
+ setup_resolutions_for_device (camera.get_selected_device ());
+ }
+
+ private void add_camera_device (void *device)
+ {
+ TreeIter iter;
+ Cheese.CameraDevice dev = (Cheese.CameraDevice) device;
+
+ camera_model.append (out iter);
+ camera_model.set (iter,
+ 0, dev.get_name () + " (" + dev.get_device_file () + ")",
+ 1, dev);
+
+ if (camera.get_selected_device ().get_device_file () == dev.get_device_file ())
+ source_combo.set_active_iter (iter);
+ }
+
+ private void remove_camera_device (TreeIter iter, Cheese.CameraDevice device_node,
+ Cheese.CameraDevice active_device_node)
+ {
+ unowned GLib.PtrArray devices = camera.get_camera_devices ();
+
+ // Check if the camera that we want to remove, is the active one
+ if (strcmp (device_node.device_file, active_device_node.device_file) == 0)
+ {
+ if (devices.len > 0)
+ set_new_available_camera_device (iter);
+ else
+ this.dialog.hide();
+ }
+ camera_model.remove (iter);
+ }
+
+ // Look for an available device and activate it.
+ private void set_new_available_camera_device (TreeIter iter)
+ {
+ TreeIter new_iter = iter;
+
+ if (!camera_model.iter_next (ref new_iter))
+ {
+ new_iter = iter;
+ camera_model.iter_previous (ref new_iter);
+ }
+ source_combo.set_active_iter (new_iter);
+ }
+
public void show ()
{
this.dialog.show_all ();
diff --git a/src/vapi/cheese-common.vapi b/src/vapi/cheese-common.vapi
index beb391c..f00a531 100644
--- a/src/vapi/cheese-common.vapi
+++ b/src/vapi/cheese-common.vapi
@@ -56,6 +56,8 @@ namespace Cheese
public Cheese.VideoFormat format {owned get; set;}
[NoAccessorMethod]
public void *video_texture {get; set;}
+ [NoAccessorMethod]
+ public uint num_camera_devices {get;}
public virtual signal void photo_saved ();
public virtual signal void photo_taken (Gdk.Pixbuf pixbuf);
public virtual signal void video_saved ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]