summaryrefslogtreecommitdiff
path: root/libcheese
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2017-11-02 09:45:33 +0100
committerOndrej Holy <oholy@redhat.com>2018-03-02 09:59:49 +0100
commitefa35e4b25c203ac92b59950e112120ae76a4d4b (patch)
tree3d178fa5a5aa3038b56984701e2bb0cb377a95f1 /libcheese
parent7b1e1b343791d933a50a63bd79a22526c62832b0 (diff)
downloadcheese-efa35e4b25c203ac92b59950e112120ae76a4d4b.tar.gz
monitor: Implement GAsyncInitable interface
Monitor initialization may block if external camera is connected, probably due to some kernel bug. It causes freezes for applications, which is not acceptable. Let's implement GAsyncInitable interface, so it can be initialized asynchronously. https://bugzilla.gnome.org/show_bug.cgi?id=782627
Diffstat (limited to 'libcheese')
-rw-r--r--libcheese/cheese-camera-device-monitor.c89
-rw-r--r--libcheese/cheese-camera-device-monitor.h6
2 files changed, 89 insertions, 6 deletions
diff --git a/libcheese/cheese-camera-device-monitor.c b/libcheese/cheese-camera-device-monitor.c
index 48520edb..5b4b43b5 100644
--- a/libcheese/cheese-camera-device-monitor.c
+++ b/libcheese/cheese-camera-device-monitor.c
@@ -47,7 +47,14 @@ struct _CheeseCameraDeviceMonitorPrivate
GstDeviceMonitor *monitor;
};
-G_DEFINE_TYPE_WITH_PRIVATE (CheeseCameraDeviceMonitor, cheese_camera_device_monitor, G_TYPE_OBJECT)
+static void initable_iface_init (GInitableIface *initable_iface);
+static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
+
+G_DEFINE_TYPE_WITH_CODE (CheeseCameraDeviceMonitor, cheese_camera_device_monitor,
+ G_TYPE_OBJECT,
+ G_ADD_PRIVATE (CheeseCameraDeviceMonitor)
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init));
#define CHEESE_CAMERA_DEVICE_MONITOR_ERROR cheese_camera_device_monitor_error_quark ()
@@ -271,10 +278,13 @@ cheese_camera_device_monitor_class_init (CheeseCameraDeviceMonitorClass *klass)
G_TYPE_NONE, 1, CHEESE_TYPE_CAMERA_DEVICE);
}
-static void
-cheese_camera_device_monitor_init (CheeseCameraDeviceMonitor *monitor)
+static gboolean
+initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
{
- CheeseCameraDeviceMonitorPrivate *priv = cheese_camera_device_monitor_get_instance_private (monitor);
+ CheeseCameraDeviceMonitor *monitor = CHEESE_CAMERA_DEVICE_MONITOR (initable);
+ CheeseCameraDeviceMonitorPrivate *priv = cheese_camera_device_monitor_get_instance_private (monitor);
GstBus *bus;
GstCaps *caps;
@@ -289,17 +299,84 @@ cheese_camera_device_monitor_init (CheeseCameraDeviceMonitor *monitor)
gst_caps_unref (caps);
gst_device_monitor_start (priv->monitor);
+
+ return TRUE;
+}
+
+static void
+initable_iface_init (GInitableIface *initable_iface)
+{
+ initable_iface->init = initable_init;
+}
+
+static void
+async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
+{
+ /* Run GInitable code in thread. */
+}
+
+static void
+cheese_camera_device_monitor_init (CheeseCameraDeviceMonitor *monitor)
+{
+ /* Let GInitable initialize it. */
}
/**
* cheese_camera_device_monitor_new:
*
- * Returns a new #CheeseCameraDeviceMonitor object.
+ * Returns a new #CheeseCameraDeviceMonitor object. The initialization may block.
+ * See cheese_camera_device_monitor_new_async() for the asynchronous version.
*
* Return value: a new #CheeseCameraDeviceMonitor object.
**/
CheeseCameraDeviceMonitor *
cheese_camera_device_monitor_new (void)
{
- return g_object_new (CHEESE_TYPE_CAMERA_DEVICE_MONITOR, NULL);
+ return g_initable_new (CHEESE_TYPE_CAMERA_DEVICE_MONITOR, NULL, NULL, NULL);
+}
+
+/**
+ * cheese_camera_device_monitor_new_async:
+ * @cancellable: a #GCancellable or NULL
+ * @callback: a GAsyncReadyCallback to call when the initialization is finished
+ * @user_data: user data to pass to callback
+ *
+ * Creates a new #CheeseCameraDeviceMonitor object asynchronously. Callback
+ * will be called when it is done. Use cheese_camera_device_monitor_new_finish()
+ * to get the result.
+ *
+ * See cheese_camera_device_monitor_new() for the synchronous version.
+ **/
+void
+cheese_camera_device_monitor_new_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (CHEESE_TYPE_CAMERA_DEVICE_MONITOR, 0, cancellable, callback, user_data, NULL);
+}
+
+/**
+ * cheese_camera_device_monitor_new_finish:
+ * @result: the GAsyncResult from the callback
+ * @error: return location for errors, or NULL to ignore
+ *
+ * Finishes creating a new #CheeseCameraDeviceMonitor object.
+ *
+ * Return value: a new #CheeseCameraDeviceMonitor object or NULL if error is set.
+ **/
+CheeseCameraDeviceMonitor *
+cheese_camera_device_monitor_new_finish (GAsyncResult *result,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source;
+
+ source = g_async_result_get_source_object (result);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error);
+ g_object_unref (source);
+
+ if (ret != NULL)
+ return CHEESE_CAMERA_DEVICE_MONITOR (ret);
+ else
+ return NULL;
}
diff --git a/libcheese/cheese-camera-device-monitor.h b/libcheese/cheese-camera-device-monitor.h
index f11d0a4c..2432bd6d 100644
--- a/libcheese/cheese-camera-device-monitor.h
+++ b/libcheese/cheese-camera-device-monitor.h
@@ -23,6 +23,7 @@
#ifndef __CHEESE_CAMERA_DEVICE_MONITOR_H__
#define __CHEESE_CAMERA_DEVICE_MONITOR_H__
+#include <gio/gio.h>
#include <glib-object.h>
#include <cheese-camera-device.h>
@@ -75,6 +76,11 @@ struct _CheeseCameraDeviceMonitorClass
GType cheese_camera_device_monitor_get_type (void);
CheeseCameraDeviceMonitor *cheese_camera_device_monitor_new (void);
+void cheese_camera_device_monitor_new_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+CheeseCameraDeviceMonitor *cheese_camera_device_monitor_new_finish (GAsyncResult *result,
+ GError **error);
void cheese_camera_device_monitor_coldplug (CheeseCameraDeviceMonitor *monitor);
G_END_DECLS