[cheese/wip/camera-service: 2/2] Import basic camera D-Bus service
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cheese/wip/camera-service: 2/2] Import basic camera D-Bus service
- Date: Mon, 18 Aug 2014 17:36:42 +0000 (UTC)
commit 91d1db75d01ca5ecf9c16b6737f4b425b9cad65b
Author: David King <amigadave amigadave com>
Date: Mon Aug 18 17:27:07 2014 +0100
Import basic camera D-Bus service
Makefile.am | 52 ++++++-
configure.ac | 4 +-
data/org.gnome.Camera.service.in | 3 +
data/org.gnome.Camera.xml | 50 ++++++
service/gc-application.c | 116 ++++++++++++++
service/gc-application.h | 45 ++++++
service/gc-camera-client.c | 298 ++++++++++++++++++++++++++++++++++++
service/gc-camera-client.h | 46 ++++++
service/gc-camera-manager.c | 295 ++++++++++++++++++++++++++++++++++++
service/gc-camera-manager.h | 45 ++++++
service/gc-chooser.c | 141 +++++++++++++++++
service/gc-chooser.h | 46 ++++++
service/gc-client-monitor.c | 311 ++++++++++++++++++++++++++++++++++++++
service/gc-client-monitor.h | 48 ++++++
service/gc-main.c | 45 ++++++
15 files changed, 1542 insertions(+), 3 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index fbcd4de..0e093f6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -251,6 +251,48 @@ cheese_LDADD = \
$(CHEESE_LIBS) \
$(CHEESE_GTK_LIBS)
+libexec_PROGRAMS = \
+ gnome-camera-service
+
+service/camera.c: service/camera.h
+service/camera.h: Makefile data/org.gnome.Camera.xml
+ $(AM_V_GEN) $(GDBUS_CODEGEN) --interface-prefix org.gnome.Camera. \
+ --generate-c-code service/camera \
+ --c-namespace Gc $(srcdir)/data/org.gnome.Camera.xml
+
+BUILT_SOURCES = \
+ $(nodist_gnome_camera_service_SOURCES)
+
+gnome_camera_service_SOURCES = \
+ service/gc-application.c \
+ service/gc-camera-client.c \
+ service/gc-camera-manager.c \
+ service/gc-client-monitor.c \
+ service/gc-main.c
+
+noinst_gnome_camera_service_headers = \
+ service/gc-application.h \
+ service/gc-camera-client.h \
+ service/gc-camera-manager.h \
+ service/gc-client-monitor.h
+
+nodist_gnome_camera_service_headers = \
+ service/camera.h
+
+nodist_gnome_camera_service_SOURCES = \
+ service/camera.c
+
+gnome_camera_service_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_builddir)/service \
+ -I$(top_srcdir)/libcheese
+
+gnome_camera_service_CFLAGS = \
+ $(CHEESE_GTK_CFLAGS)
+
+gnome_camera_service_LDADD = \
+ libcheese-gtk.la
+
EXAMPLES = \
tests/cheese-test-camera \
tests/cheese-test-chooser \
@@ -322,7 +364,9 @@ appdata_in_files = data/org.gnome.Cheese.appdata.xml.in
appdata_XML = $(appdata_in_files:.appdata.xml.in=.appdata.xml)
servicedir = $(datadir)/dbus-1/services
-service_DATA = data/org.gnome.Cheese.service
+service_DATA = \
+ data/org.gnome.Camera.service \
+ data/org.gnome.Cheese.service
@GSETTINGS_RULES@
gsettings_SCHEMAS = data/org.gnome.Cheese.gschema.xml
@@ -487,9 +531,11 @@ dist_noinst_DATA = \
ChangeLog.pre-git \
$(desktop_in_files) \
$(gsettings_SCHEMAS) \
+ $(noinst_gnome_camera_service_headers) \
$(noinst_resource_files) \
$(appdata_in_files) \
data/org.gnome.Cheese.gresource.xml \
+ data/org.gnome.Camera.xml \
build-aux/test-driver \
$(gtkdoc_srcdir)/cheese-docs.xml \
$(gtkdoc_srcdir)/cheese-sections.txt \
@@ -519,8 +565,10 @@ CLEANFILES = \
$(enum_data) \
$(gir_DATA) \
$(typelib_DATA) \
+ $(nodist_gnome_camera_service_headers) \
src/cheese-resource.c \
- src/cheese-resource.h
+ src/cheese-resource.h \
+ service/camera.h
DISTCLEANFILES = \
libcheese_la_vala.stamp \
diff --git a/configure.ac b/configure.ac
index c2fbdce..b904858 100644
--- a/configure.ac
+++ b/configure.ac
@@ -119,8 +119,9 @@ PKG_CHECK_MODULES([CHEESE_GTK],
$UDEV_REQUIRED
$GNOME_VIDEO_EFFECTS_REQUIRED])
-# Resources.
+# GLib programs.
AC_SUBST([GLIB_COMPILE_RESOURCES], [`$PKG_CONFIG --variable glib_compile_resources gio-2.0`])
+AC_SUBST([GDBUS_CODEGEN], [`$PKG_CONFIG --variable gdbus_codegen gio-2.0`])
# Recommend some runtime GStreamer plugins.
AC_PATH_PROGS([GST_INSPECT], [gst-inspect-1.0], [notfound])
@@ -217,6 +218,7 @@ docs/reference/Makefile
docs/reference/version.xml
data/cheese.pc
data/cheese-gtk.pc
+data/org.gnome.Camera.service
data/org.gnome.Cheese.desktop.in
data/org.gnome.Cheese.service
help/Makefile
diff --git a/data/org.gnome.Camera.service.in b/data/org.gnome.Camera.service.in
new file mode 100644
index 0000000..de474f0
--- /dev/null
+++ b/data/org.gnome.Camera.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.Camera
+Exec= libexecdir@/gnome-camera-service
diff --git a/data/org.gnome.Camera.xml b/data/org.gnome.Camera.xml
new file mode 100644
index 0000000..4a6926c
--- /dev/null
+++ b/data/org.gnome.Camera.xml
@@ -0,0 +1,50 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/org/gnome/Camera">
+ <!-- org.gnome.Camera:
+ @short_description: Use the available camera devices
+
+ The camera interface is used to take photos with the available camera
+ devices.
+ -->
+ <interface name="org.gnome.Camera.Manager">
+ <!-- GetClient:
+ @chooser: The object path of a new client object
+ @short_description: Get a client object for showing a photo dialog
+
+ Use the obtained client object to show a dialog for taking photos
+ and videos using a webcam.
+ -->
+ <method name="GetClient">
+ <arg name="client" type="o" direction="out"/>
+ </method>
+ </interface>
+
+ <!-- org.gnome.Camera.Client:
+ @short_description: Play images and videos from a camera
+ -->
+ <interface name="org.gnome.Camera.Client">
+ <!-- ImageData:
+ @short_description: Image data for photo from webcam
+
+ The PNG image data, Base64-encoded, from the photo taken by the
+ webcam, and cropped by the user.
+ -->
+ <property name="ImageData" type="s" access="read">
+ <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/>
+ </property>
+ <!-- ShowChooser:
+ @short_description: Show the webcam chooser dialog
+ -->
+ <method name="ShowChooser">
+ </method>
+ <!-- UserDone:
+ @photo_taken: Whether a photo was taken or not
+ @image_data: The image data as a Base64-encoded PNG, or empty
+ @short_description: Indicates that the dialog was closed
+ -->
+ <signal name="UserDone">
+ <arg name="photo_taken" type="b" />
+ <arg name="image_data" type="s" />
+ </signal>
+ </interface>
+</node>
diff --git a/service/gc-application.c b/service/gc-application.c
new file mode 100644
index 0000000..7e0d086
--- /dev/null
+++ b/service/gc-application.c
@@ -0,0 +1,116 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gc-application.h"
+
+#include "gc-camera-manager.h"
+
+typedef struct
+{
+ GcCameraManager *manager;
+} GcApplicationPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GcApplication, gc_application, G_TYPE_APPLICATION)
+
+static gboolean
+gc_application_dbus_register (GApplication *application,
+ GDBusConnection *connection,
+ const gchar *object_path,
+ GError **error)
+{
+ GcApplicationPrivate *priv;
+
+ priv = gc_application_get_instance_private (GC_APPLICATION (application));
+
+ if (!G_APPLICATION_CLASS (gc_application_parent_class)->dbus_register (application,
+ connection,
+ object_path,
+ error))
+ {
+ return FALSE;
+ }
+
+ priv->manager = gc_camera_manager_new (connection, error);
+
+ if (priv->manager == NULL)
+ {
+ g_warning ("Error exporting camera interface skeleton: %s",
+ (*error)->message);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+gc_application_dbus_unregister (GApplication *application,
+ GDBusConnection *connection,
+ const gchar *object_path)
+{
+ GcApplicationPrivate *priv;
+
+ priv = gc_application_get_instance_private (GC_APPLICATION (application));
+
+ /* TODO: Not necessary? */
+ g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (priv->manager));
+
+ G_APPLICATION_CLASS (gc_application_parent_class)->dbus_unregister (application,
+ connection,
+ object_path);
+}
+
+static void
+gc_application_finalize (GObject *object)
+{
+ GcApplication *application;
+ GcApplicationPrivate *priv;
+
+ application = GC_APPLICATION (object);
+ priv = gc_application_get_instance_private (application);
+
+ g_clear_object (&priv->manager);
+}
+
+static void
+gc_application_init (GcApplication *application)
+{
+}
+
+static void
+gc_application_class_init (GcApplicationClass *klass)
+{
+ GObjectClass *gobject_class;
+ GApplicationClass *app_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = gc_application_finalize;
+
+ app_class = G_APPLICATION_CLASS (klass);
+ app_class->dbus_register = gc_application_dbus_register;
+ app_class->dbus_unregister = gc_application_dbus_unregister;
+}
+
+GcApplication *
+gc_application_new (void)
+{
+ return g_object_new (GC_TYPE_APPLICATION, "application-id",
+ "org.gnome.Camera", "flags", G_APPLICATION_IS_SERVICE,
+ NULL);
+}
diff --git a/service/gc-application.h b/service/gc-application.h
new file mode 100644
index 0000000..a74a6ea
--- /dev/null
+++ b/service/gc-application.h
@@ -0,0 +1,45 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GC_APPLICATION_H_
+#define GC_APPLICATION_H_
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ /*< private >*/
+ GApplication parent_instance;
+} GcApplication;
+
+typedef struct
+{
+ GApplicationClass parent_class;
+} GcApplicationClass;
+
+#define GC_TYPE_APPLICATION (gc_application_get_type ())
+#define GC_APPLICATION(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GC_TYPE_APPLICATION, GcApplication))
+
+GType gc_application_get_type (void);
+GcApplication * gc_application_new (void);
+
+G_END_DECLS
+
+#endif /* GC_APPLICATION_H_ */
diff --git a/service/gc-camera-client.c b/service/gc-camera-client.c
new file mode 100644
index 0000000..5436564
--- /dev/null
+++ b/service/gc-camera-client.c
@@ -0,0 +1,298 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gc-camera-client.h"
+
+#include <cheese/cheese-avatar-chooser.h>
+
+typedef struct
+{
+ GDBusConnection *connection;
+ gchar *path;
+ GtkWidget *chooser;
+ gchar *image_data;
+} GcCameraClientPrivate;
+
+static void gc_camera_client_client_iface_init (GcClientIface *iface);
+static void gc_camera_client_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcCameraClient, gc_camera_client,
+ GC_TYPE_CLIENT_SKELETON,
+ G_ADD_PRIVATE (GcCameraClient)
+ G_IMPLEMENT_INTERFACE (GC_TYPE_CLIENT, gc_camera_client_client_iface_init)
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gc_camera_client_initable_iface_init))
+
+enum
+{
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_PATH,
+ PROP_IMAGE_DATA,
+ N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void
+gc_camera_client_set_image_data_from_pixbuf (GcCameraClient *self,
+ GdkPixbuf *pixbuf)
+{
+ GcCameraClientPrivate *priv;
+ gchar *buffer;
+ gsize length;
+
+ priv = gc_camera_client_get_instance_private (self);
+
+ /* FIXME: Check for errors. */
+ if (!gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &length, "png", NULL, NULL))
+ {
+ g_error ("%s", "GdkPixbuf could not be saved to PNG format");
+ }
+
+ g_free (priv->image_data);
+ priv->image_data = g_base64_encode (buffer, length);
+ g_free (buffer);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IMAGE_DATA]);
+}
+
+static void
+on_chooser_response (CheeseAvatarChooser *chooser,
+ gint response,
+ GcCameraClient *self)
+{
+ GcCameraClientPrivate *priv;
+
+ priv = gc_camera_client_get_instance_private (self);
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ {
+ gc_camera_client_set_image_data_from_pixbuf (self,
+ cheese_avatar_chooser_get_picture (chooser));
+ gc_client_emit_user_done (GC_CLIENT (self), TRUE, priv->image_data);
+ }
+ else
+ {
+ gc_client_emit_user_done (GC_CLIENT (self), FALSE, priv->image_data);
+ }
+
+ /* FIXME: Destroy the chooser, as there is no way to stop the webcam
+ * viewfinder. */
+ gtk_widget_hide (GTK_WIDGET (chooser));
+}
+
+static gboolean
+gc_camera_client_handle_show_chooser (GcClient *client,
+ GDBusMethodInvocation *invocation)
+{
+ GcCameraClientPrivate *priv;
+
+ priv = gc_camera_client_get_instance_private (GC_CAMERA_CLIENT (client));
+
+ gtk_widget_show (priv->chooser);
+
+ gc_client_complete_show_chooser (client, invocation);
+
+ return TRUE;
+}
+
+static const gchar *
+gc_camera_client_get_image_data (GcClient *client)
+{
+ GcCameraClient *self;
+ GcCameraClientPrivate *priv;
+
+ self = GC_CAMERA_CLIENT (client);
+ priv = gc_camera_client_get_instance_private (self);
+
+ return priv->image_data;
+}
+
+const gchar *
+gc_camera_client_get_path (GcCameraClient *client)
+{
+ GcCameraClientPrivate *priv;
+
+ g_return_val_if_fail (GC_CAMERA_CLIENT (client), NULL);
+
+ priv = gc_camera_client_get_instance_private (client);
+
+ return priv->path;
+}
+
+static void
+gc_camera_client_finalize (GObject *object)
+{
+ GcCameraClientPrivate *priv;
+
+ priv = gc_camera_client_get_instance_private (GC_CAMERA_CLIENT (object));
+
+ g_clear_object (&priv->chooser);
+ g_clear_pointer (&priv->image_data, g_free);
+
+ g_free (priv->path);
+
+ G_OBJECT_CLASS (gc_camera_client_parent_class)->finalize (object);
+}
+
+static void
+gc_camera_client_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GcCameraClientPrivate *priv;
+
+ priv = gc_camera_client_get_instance_private (GC_CAMERA_CLIENT (object));
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ g_value_set_object (value, priv->connection);
+ break;
+ case PROP_PATH:
+ g_value_set_string (value, priv->path);
+ break;
+ case PROP_IMAGE_DATA:
+ g_value_set_string (value, priv->image_data);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gc_camera_client_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcCameraClientPrivate *priv;
+
+ priv = gc_camera_client_get_instance_private (GC_CAMERA_CLIENT (object));
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ priv->connection = g_value_dup_object (value);
+ break;
+ case PROP_PATH:
+ g_free (priv->path);
+ priv->path = g_value_dup_string (value);
+ break;
+ case PROP_IMAGE_DATA:
+ g_free (priv->image_data);
+ priv->image_data = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gc_camera_client_class_init (GcCameraClientClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gc_camera_client_finalize;
+ object_class->get_property = gc_camera_client_get_property;
+ object_class->set_property = gc_camera_client_set_property;
+
+ properties[PROP_CONNECTION] = g_param_spec_object ("connection",
+ "Connection",
+ "DBus Connection",
+ G_TYPE_DBUS_CONNECTION,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION,
+ properties[PROP_CONNECTION]);
+
+ properties[PROP_PATH] = g_param_spec_string ("path",
+ "Path",
+ "D-Bus object path",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_PATH,
+ properties[PROP_PATH]);
+
+ properties[PROP_IMAGE_DATA] = g_param_spec_string ("image-data",
+ "Image data",
+ "PNG image data, Base64-encoded",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_IMAGE_DATA,
+ properties[PROP_IMAGE_DATA]);
+}
+
+static void
+gc_camera_client_init (GcCameraClient *self)
+{
+ GcCameraClientPrivate *priv;
+
+ priv = gc_camera_client_get_instance_private (self);
+
+ priv->chooser = cheese_avatar_chooser_new ();
+
+ g_signal_connect (priv->chooser, "response",
+ G_CALLBACK (on_chooser_response), self);
+}
+
+static gboolean
+gc_camera_client_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GcCameraClientPrivate *priv;
+
+ priv = gc_camera_client_get_instance_private (GC_CAMERA_CLIENT (initable));
+
+ return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (initable),
+ priv->connection,
+ priv->path,
+ error);
+}
+
+static void
+gc_camera_client_client_iface_init (GcClientIface *iface)
+{
+ iface->handle_show_chooser = gc_camera_client_handle_show_chooser;
+ iface->get_image_data = gc_camera_client_get_image_data;
+}
+
+static void
+gc_camera_client_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = gc_camera_client_initable_init;
+}
+
+GcCameraClient *
+gc_camera_client_new (GDBusConnection *connection,
+ const gchar *path,
+ GError **error)
+{
+ return g_initable_new (GC_TYPE_CAMERA_CLIENT, NULL, error, "connection",
+ connection, "path", path, NULL);
+}
diff --git a/service/gc-camera-client.h b/service/gc-camera-client.h
new file mode 100644
index 0000000..d611451
--- /dev/null
+++ b/service/gc-camera-client.h
@@ -0,0 +1,46 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GC_CAMERA_CLIENT_H_
+#define GC_CAMERA_CLIENT_H_
+
+#include "camera.h"
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ /*< private >*/
+ GcClientSkeleton parent_instance;
+} GcCameraClient;
+
+typedef struct
+{
+ GcClientSkeletonClass parent_class;
+} GcCameraClientClass;
+
+#define GC_TYPE_CAMERA_CLIENT (gc_camera_client_get_type ())
+#define GC_CAMERA_CLIENT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GC_TYPE_CAMERA_CLIENT,
GcCameraClient))
+
+GType gc_camera_client_get_type (void);
+GcCameraClient * gc_camera_client_new (GDBusConnection *connection, const gchar *path, GError **error);
+const gchar * gc_camera_client_get_path (GcCameraClient *client);
+
+G_END_DECLS
+
+#endif /* GC_CAMERA_CLIENT_H_ */
diff --git a/service/gc-camera-manager.c b/service/gc-camera-manager.c
new file mode 100644
index 0000000..94b18ea
--- /dev/null
+++ b/service/gc-camera-manager.c
@@ -0,0 +1,295 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gc-camera-manager.h"
+
+#include "gc-camera-client.h"
+#include "gc-client-monitor.h"
+
+typedef struct
+{
+ GDBusConnection *connection;
+ GStrv cameras;
+ GHashTable *clients;
+ guint client_ids;
+} GcCameraManagerPrivate;
+
+static void gc_camera_manager_manager_iface_init (GcManagerIface *iface);
+static void gc_camera_manager_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcCameraManager, gc_camera_manager,
+ GC_TYPE_MANAGER_SKELETON,
+ G_ADD_PRIVATE (GcCameraManager)
+ G_IMPLEMENT_INTERFACE (GC_TYPE_MANAGER, gc_camera_manager_manager_iface_init)
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gc_camera_manager_initable_iface_init))
+
+typedef struct
+{
+ GcCameraManager *manager;
+ GDBusMethodInvocation *invocation;
+ GcClientMonitor *monitor;
+} OnClientMonitorNewReadyData;
+
+enum
+{
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_CAMERAS,
+ N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+
+static void
+on_client_monitor_new_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ OnClientMonitorNewReadyData *data;
+ GcClientMonitor *monitor;
+ GError *error = NULL;
+ GcCameraManager *self;
+ GcCameraManagerPrivate *priv;
+ gchar *path;
+ GcCameraClient *client;
+
+ data = (OnClientMonitorNewReadyData *)user_data;
+ monitor = gc_client_monitor_new_finish (result, &error);
+
+ if (monitor == NULL)
+ {
+ g_dbus_method_invocation_return_error (data->invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "%s",
+ error->message);
+ g_error_free (error);
+ g_slice_free (OnClientMonitorNewReadyData, data);
+
+ return;
+ }
+
+ self = data->manager;
+ priv = gc_camera_manager_get_instance_private (self);
+
+ path = g_strdup_printf ("/org/gnome/Camera/Client/%d", ++priv->client_ids);
+
+ /* FIXME: Do this properly when adding multiple client handling. */
+ g_application_hold (g_application_get_default ());
+
+ client = gc_camera_client_new (priv->connection, path, &error);
+
+ if (client == NULL)
+ {
+ goto error_out;
+ }
+
+ g_hash_table_insert (priv->clients, path, client);
+
+ gc_manager_complete_get_client (GC_MANAGER (self), data->invocation, path);
+
+ goto out;
+
+error_out:
+ g_dbus_method_invocation_return_error (data->invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "%s",
+ error->message);
+ g_error_free (error);
+
+out:
+ g_clear_object (&monitor);
+ g_slice_free (OnClientMonitorNewReadyData, data);
+ g_free (path);
+}
+
+static gboolean
+gc_camera_manager_handle_get_client (GcManager *manager,
+ GDBusMethodInvocation *invocation)
+{
+ GcCameraManager *self;
+ GcCameraManagerPrivate *priv;
+ const gchar *peer;
+ GcCameraClient *client;
+ OnClientMonitorNewReadyData *data;
+
+ self = GC_CAMERA_MANAGER (manager);
+ priv = gc_camera_manager_get_instance_private (self);
+
+ peer = g_dbus_method_invocation_get_sender (invocation);
+ client = g_hash_table_lookup (priv->clients, peer);
+
+ if (client != NULL)
+ {
+ const gchar *path;
+
+ path = gc_camera_client_get_path (client);
+ gc_manager_complete_get_client (manager, invocation, path);
+ return TRUE;
+ }
+
+ /* FIXME: Monitor when the associated peer disappears from the bus. */
+ data = g_slice_new (OnClientMonitorNewReadyData);
+ data->manager = self;
+ data->invocation = invocation;
+ gc_client_monitor_new_async (peer,
+ priv->connection,
+ NULL,
+ on_client_monitor_new_ready,
+ data);
+
+ return TRUE;
+}
+
+static void
+gc_camera_manager_finalize (GObject *object)
+{
+ GcCameraManagerPrivate *priv;
+
+ priv = gc_camera_manager_get_instance_private (GC_CAMERA_MANAGER (object));
+
+ g_clear_object (&priv->connection);
+ g_clear_pointer (&priv->clients, g_hash_table_unref);
+
+ G_OBJECT_CLASS (gc_camera_manager_parent_class)->finalize (object);
+}
+
+static void
+gc_camera_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GcCameraManagerPrivate *priv;
+
+ priv = gc_camera_manager_get_instance_private (GC_CAMERA_MANAGER (object));
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ g_value_set_object (value, priv->connection);
+ break;
+ case PROP_CAMERAS:
+ g_value_set_boxed (value, priv->cameras);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gc_camera_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcCameraManagerPrivate *priv;
+
+ priv = gc_camera_manager_get_instance_private (GC_CAMERA_MANAGER (object));
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ priv->connection = g_value_dup_object (value);
+ break;
+ case PROP_CAMERAS:
+ g_strfreev (priv->cameras);
+ priv->cameras = g_value_dup_boxed (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gc_camera_manager_class_init (GcCameraManagerClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gc_camera_manager_finalize;
+ object_class->get_property = gc_camera_manager_get_property;
+ object_class->set_property = gc_camera_manager_set_property;
+
+ properties[PROP_CONNECTION] = g_param_spec_object ("connection",
+ "Connection",
+ "DBus Connection",
+ G_TYPE_DBUS_CONNECTION,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CONNECTION,
+ properties[PROP_CONNECTION]);
+
+ properties[PROP_CAMERAS] = g_param_spec_boxed ("cameras",
+ "Cameras",
+ "List of connected cameras",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CAMERAS,
+ properties[PROP_CAMERAS]);
+}
+
+static void
+gc_camera_manager_init (GcCameraManager *self)
+{
+}
+
+static gboolean
+gc_camera_manager_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GcCameraManagerPrivate *priv;
+
+ priv = gc_camera_manager_get_instance_private (GC_CAMERA_MANAGER (initable));
+
+ priv->clients = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (initable),
+ priv->connection,
+ "/org/gnome/Camera/Manager",
+ error);
+}
+
+static void
+gc_camera_manager_manager_iface_init (GcManagerIface *iface)
+{
+ iface->handle_get_client = gc_camera_manager_handle_get_client;
+}
+
+static void
+gc_camera_manager_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = gc_camera_manager_initable_init;
+}
+
+GcCameraManager *
+gc_camera_manager_new (GDBusConnection *connection, GError **error)
+{
+ return g_initable_new (GC_TYPE_CAMERA_MANAGER, NULL, error, "connection",
+ connection, NULL);
+}
diff --git a/service/gc-camera-manager.h b/service/gc-camera-manager.h
new file mode 100644
index 0000000..00965c3
--- /dev/null
+++ b/service/gc-camera-manager.h
@@ -0,0 +1,45 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GC_CAMERA_MANAGER_H_
+#define GC_CAMERA_MANAGER_H_
+
+#include "camera.h"
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ /*< private >*/
+ GcManagerSkeleton parent_instance;
+} GcCameraManager;
+
+typedef struct
+{
+ GcManagerSkeletonClass parent_class;
+} GcCameraManagerClass;
+
+#define GC_TYPE_CAMERA_MANAGER (gc_camera_manager_get_type ())
+#define GC_CAMERA_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GC_TYPE_CAMERA_MANAGER,
GcCameraManager))
+
+GType gc_camera_manager_get_type (void);
+GcCameraManager * gc_camera_manager_new (GDBusConnection *connection, GError **error);
+
+G_END_DECLS
+
+#endif /* GC_CAMERA_MANAGER_H_ */
diff --git a/service/gc-chooser.c b/service/gc-chooser.c
new file mode 100644
index 0000000..9cbdb43
--- /dev/null
+++ b/service/gc-chooser.c
@@ -0,0 +1,141 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gc-chooser.h"
+
+#include <glib/gi18n.h>
+#include <clutter-gst/clutter-gst.h>
+#include <clutter-gtk/clutter-gtk.h>
+
+typedef struct
+{
+ GtkWidget *camera_embed;
+ ClutterActor *stage;
+ ClutterGstCamera *camera;
+ ClutterActor *camera_actor;
+ const GPtrArray *devices;
+} GcChooserPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GcChooser, gc_chooser, GTK_TYPE_DIALOG)
+
+static void
+on_gc_chooser_response (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ switch (response_id)
+ {
+ default:
+ return;
+ }
+}
+
+static void
+set_default_camera_resolutions (GcChooser *chooser)
+{
+ GcChooserPrivate *priv;
+ guint i;
+
+ priv = gc_chooser_get_instance_private (chooser);
+
+ priv->devices = clutter_gst_camera_manager_get_camera_devices (clutter_gst_camera_manager_get_default
());
+
+ for (i = 0; i < priv->devices->len; i++)
+ {
+ ClutterGstCameraDevice *device;
+
+ device = g_ptr_array_index (priv->devices, i);
+
+ clutter_gst_camera_device_set_capture_resolution (device, 640, 480);
+ }
+}
+
+static void
+add_default_camera_device (GcChooser *chooser)
+{
+ GcChooserPrivate *priv;
+ ClutterContent *ratio;
+
+ priv = gc_chooser_get_instance_private (chooser);
+
+ priv->camera = clutter_gst_camera_new ();
+ priv->camera_actor = clutter_actor_new ();
+
+ ratio = clutter_gst_aspectratio_new ();
+ clutter_gst_content_set_player (CLUTTER_GST_CONTENT (ratio),
+ CLUTTER_GST_PLAYER (priv->camera));
+
+ clutter_actor_set_content (priv->camera_actor, ratio);
+ clutter_actor_add_child (priv->stage, priv->camera_actor);
+
+ /* TODO: Use something other than the default camera device. */
+ set_default_camera_resolutions (chooser);
+
+ clutter_gst_player_set_playing (CLUTTER_GST_PLAYER (priv->camera), TRUE);
+ clutter_actor_show (priv->stage);
+}
+
+static void
+gc_chooser_class_init (GcChooserClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/Camera/gc-chooser.ui");
+
+ gtk_widget_class_bind_template_child_private (widget_class, GcChooser,
+ camera_embed);
+ gtk_widget_class_bind_template_callback (widget_class,
+ on_gc_chooser_response);
+}
+
+static void
+gc_chooser_init (GcChooser *chooser)
+{
+ GcChooserPrivate *priv;
+ GtkWidget *button;
+ ClutterColor stage_colour = { 0x00, 0x00, 0x00, 0x00 };
+
+ priv = gc_chooser_get_instance_private (chooser);
+
+ gtk_widget_init_template (GTK_WIDGET (chooser));
+
+ /* FIXME: Translatable strings. */
+ gtk_dialog_add_buttons (GTK_DIALOG (chooser), "Select",
+ GTK_RESPONSE_ACCEPT, "Cancel", GTK_RESPONSE_CANCEL,
+ NULL);
+
+ button = gtk_dialog_get_widget_for_response (GTK_DIALOG (chooser),
+ GTK_RESPONSE_ACCEPT);
+ gtk_style_context_add_class (gtk_widget_get_style_context (button),
+ GTK_STYLE_CLASS_SUGGESTED_ACTION);
+
+ priv->stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (priv->camera_embed));
+
+ clutter_actor_set_size (priv->stage, 640, 480);
+ clutter_stage_set_minimum_size (CLUTTER_STAGE (priv->stage), 320, 240);
+ clutter_actor_set_background_color (priv->stage, &stage_colour);
+
+ add_default_camera_device (chooser);
+}
+
+GtkWidget *
+gc_chooser_new (void)
+{
+ return g_object_new (GC_TYPE_CHOOSER, "use-header-bar", TRUE, NULL);
+}
diff --git a/service/gc-chooser.h b/service/gc-chooser.h
new file mode 100644
index 0000000..763f8fe
--- /dev/null
+++ b/service/gc-chooser.h
@@ -0,0 +1,46 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GC_CHOOSER_H_
+#define GC_CHOOSER_H_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ /*< private >*/
+ GtkDialog parent_instance;
+} GcChooser;
+
+typedef struct
+{
+ /*< private >*/
+ GtkDialogClass parent_class;
+} GcChooserClass;
+
+#define GC_TYPE_CHOOSER (gc_chooser_get_type ())
+#define GC_CHOOSER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GC_TYPE_CHOOSER, GcChooser))
+
+GType gc_chooser_get_type (void);
+GtkWidget * gc_chooser_new (void);
+
+G_END_DECLS
+
+#endif /* GC_CHOOSER_H_ */
diff --git a/service/gc-client-monitor.c b/service/gc-client-monitor.c
new file mode 100644
index 0000000..61ce70a
--- /dev/null
+++ b/service/gc-client-monitor.c
@@ -0,0 +1,311 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gc-client-monitor.h"
+
+typedef struct
+{
+ gchar *peer;
+ GDBusConnection *connection;
+ GDBusProxy *dbus_proxy;
+ guint watch_id;
+ guint32 user_id;
+} GcClientMonitorPrivate;
+
+static void gc_client_monitor_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GcClientMonitor,
+ gc_client_monitor,
+ G_TYPE_OBJECT,
+ G_ADD_PRIVATE (GcClientMonitor)
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
gc_client_monitor_async_initable_iface_init))
+
+enum
+{
+ PROP_0,
+ PROP_CONNECTION,
+ PROP_PEER,
+ N_PROPERTIES
+};
+
+enum
+{
+ PEER_VANISHED,
+ N_SIGNALS
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
+static guint signals[N_SIGNALS];
+
+static void
+on_name_vanished (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ g_signal_emit (GC_CLIENT_MONITOR (user_data), signals[PEER_VANISHED], 0);
+}
+
+static void
+on_get_user_id_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GTask *task;
+ GcClientMonitor *self;
+ GcClientMonitorPrivate *priv;
+ GError *error = NULL;
+ GVariant *results = NULL;
+
+ task = G_TASK (user_data);
+ self = GC_CLIENT_MONITOR (g_task_get_source_object (task));
+ priv = gc_client_monitor_get_instance_private (self);
+
+ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ result,
+ &error);
+ if (results == NULL)
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+
+ return;
+ }
+
+ g_assert (g_variant_n_children (results) > 0);
+ g_variant_get_child (results, 0, "u", &priv->user_id);
+ g_variant_unref (results);
+
+ priv->watch_id = g_bus_watch_name_on_connection (priv->connection,
+ priv->peer,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ NULL,
+ on_name_vanished,
+ self,
+ NULL);
+
+ g_task_return_boolean (task, TRUE);
+
+ g_object_unref (task);
+}
+
+static void
+on_dbus_proxy_ready (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GTask *task;
+ GcClientMonitor *self;
+ GcClientMonitorPrivate *priv;
+ GError *error = NULL;
+
+ task = G_TASK (user_data);
+ self = GC_CLIENT_MONITOR (g_task_get_source_object (task));
+ priv = gc_client_monitor_get_instance_private (self);
+
+ priv->dbus_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
+
+ if (priv->dbus_proxy == NULL)
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ g_dbus_proxy_call (priv->dbus_proxy,
+ "GetConnectionUnixUser",
+ g_variant_new ("(s)", priv->peer),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ g_task_get_cancellable (task),
+ on_get_user_id_ready,
+ task);
+}
+
+static void
+gc_client_monitor_finalize (GObject *object)
+{
+ GcClientMonitorPrivate *priv;
+
+ priv = gc_client_monitor_get_instance_private (GC_CLIENT_MONITOR (object));
+
+ g_free (priv->peer);
+
+ G_OBJECT_CLASS (gc_client_monitor_parent_class)->finalize (object);
+}
+
+static void
+gc_client_monitor_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GcClientMonitorPrivate *priv;
+
+ priv = gc_client_monitor_get_instance_private (GC_CLIENT_MONITOR (object));
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ g_value_set_object (value, priv->connection);
+ break;
+ case PROP_PEER:
+ g_value_set_string (value, priv->peer);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gc_client_monitor_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcClientMonitorPrivate *priv;
+
+ priv = gc_client_monitor_get_instance_private (GC_CLIENT_MONITOR (object));
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ priv->connection = g_value_dup_object (value);
+ break;
+ case PROP_PEER:
+ g_free (priv->peer);
+ priv->peer = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gc_client_monitor_class_init (GcClientMonitorClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gc_client_monitor_finalize;
+ object_class->get_property = gc_client_monitor_get_property;
+ object_class->set_property = gc_client_monitor_set_property;
+
+ properties[PROP_CONNECTION] = g_param_spec_object ("connection",
+ "Connection",
+ "DBus Connection",
+ G_TYPE_DBUS_CONNECTION,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_PEER] = g_param_spec_string ("peer",
+ "Peer",
+ "D-Bus object path of peer to monitor",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+}
+
+static void
+gc_client_monitor_init (GcClientMonitor *self)
+{
+}
+
+static void
+gc_client_monitor_async_initable_init_async (GAsyncInitable *initable,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (initable, cancellable, callback, user_data);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ cancellable,
+ on_dbus_proxy_ready,
+ task);
+}
+
+static gboolean
+gc_client_monitor_async_initable_init_finish (GAsyncInitable *initable,
+ GAsyncResult *result,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+gc_client_monitor_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+ iface->init_async = gc_client_monitor_async_initable_init_async;
+ iface->init_finish = gc_client_monitor_async_initable_init_finish;
+}
+
+void
+gc_client_monitor_new_async (const gchar *peer,
+ GDBusConnection *connection,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (GC_TYPE_CLIENT_MONITOR,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ "connection",
+ connection,
+ "peer",
+ peer,
+ NULL);
+}
+
+GcClientMonitor *
+gc_client_monitor_new_finish (GAsyncResult *result, GError **error)
+{
+ GObject *object;
+ GObject *source_object;
+
+ source_object = g_async_result_get_source_object (result);
+ object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
+ result,
+ error);
+ g_object_unref (source_object);
+
+ if (object != NULL)
+ {
+ return GC_CLIENT_MONITOR (object);
+ }
+ else
+ {
+ return NULL;
+ }
+}
diff --git a/service/gc-client-monitor.h b/service/gc-client-monitor.h
new file mode 100644
index 0000000..2da6f3b
--- /dev/null
+++ b/service/gc-client-monitor.h
@@ -0,0 +1,48 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GC_CLIENT_MONITOR_H_
+#define GC_CLIENT_MONITOR_H_
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ /*< private >*/
+ GObject parent_instance;
+} GcClientMonitor;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ void (* peer_vanished) (GcClientMonitor *self);
+} GcClientMonitorClass;
+
+#define GC_TYPE_CLIENT_MONITOR (gc_client_monitor_get_type ())
+#define GC_CLIENT_MONITOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GC_TYPE_CLIENT_MONITOR,
GcClientMonitor))
+
+GType gc_client_monitor_get_type (void);
+void gc_client_monitor_new_async (const gchar *bus_name, GDBusConnection *connection, GCancellable
*cancellable, GAsyncReadyCallback callback, gpointer user_data);
+GcClientMonitor * gc_client_monitor_new_finish (GAsyncResult *result, GError **error);
+
+G_END_DECLS
+
+#endif /* GC_CLIENT_MONITOR_H_ */
diff --git a/service/gc-main.c b/service/gc-main.c
new file mode 100644
index 0000000..71a301d
--- /dev/null
+++ b/service/gc-main.c
@@ -0,0 +1,45 @@
+/*
+ * GNOME Camera - Access camera devices on a system via D-Bus
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+#include <cheese/cheese-gtk.h>
+#include <clutter-gtk/clutter-gtk.h>
+
+#include "gc-application.h"
+
+int
+main (int argc,
+ char *argv[])
+{
+ GApplication *application;
+ int status;
+
+ if (!cheese_gtk_init (&argc, &argv))
+ {
+ return 1;
+ }
+
+ g_set_prgname (PACKAGE_TARNAME);
+ application = G_APPLICATION (gc_application_new ());
+ status = g_application_run (application, argc, argv);
+ g_object_unref (application);
+
+ return status;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]