diff --git a/src/Makefile.am b/src/Makefile.am
index 666d48fa2..e5770e7be 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -84,11 +84,12 @@ client/pv-enumtypes.c: $(enumtypesincludes) client/pv-enumtypes.h
dbus/org-pulsevideo.c: dbus/org-pulsevideo.h
dbus/org-pulsevideo.h: dbus/org.pulsevideo.xml
$(AM_V_GEN) $(GDBUS_CODEGEN) \
- --c-generate-object-manager \
--interface-prefix org.pulsevideo. \
--generate-c-code dbus/org-pulsevideo \
--generate-docbook ../doc/org-pulsevideo \
- --c-namespace Pv dbus/org.pulsevideo.xml
+ --c-namespace Pv dbus/org.pulsevideo.xml \
+ --c-generate-object-manager
+
built_header_make = client/pv-enumtypes.h dbus/org-pulsevideo.h
built_source_make = client/pv-enumtypes.c dbus/org-pulsevideo.c
@@ -192,6 +193,7 @@ lib_LTLIBRARIES += libpulsevideocore-@PV_MAJORMINOR@.la
# Pure core stuff
libpulsevideocore_@PV_MAJORMINOR@_la_SOURCES = \
server/pv-client.c server/pv-client.h \
+ server/pv-source-provider.c server/pv-source-provider.h \
server/pv-daemon.c server/pv-daemon.h \
modules/v4l2/pv-v4l2-source.c
diff --git a/src/client/pv-source.c b/src/client/pv-source.c
index 8adb0ea78..7071372dc 100644
--- a/src/client/pv-source.c
+++ b/src/client/pv-source.c
@@ -92,6 +92,28 @@ pv_source_set_property (GObject *_object,
break;
}
}
+
+static gboolean
+handle_create_source_output (PvSource1 *interface,
+ GDBusMethodInvocation *invocation,
+ GVariant *arg_properties,
+ gpointer user_data)
+{
+ PvSource *source = user_data;
+ PvSourcePrivate *priv = source->priv;
+ PvSourceOutput *output;
+ const gchar *object_path;
+
+ output = pv_source_create_source_output (source, arg_properties, priv->object_path);
+
+ object_path = pv_source_output_get_object_path (output);
+
+ pv_source1_complete_create_source_output (interface,
+ invocation,
+ object_path);
+ return TRUE;
+}
+
static void
source_register_object (PvSource *source)
{
@@ -103,6 +125,7 @@ source_register_object (PvSource *source)
PvSource1 *iface;
iface = pv_source1_skeleton_new ();
+ g_signal_connect (iface, "handle-create-source-output", (GCallback) handle_create_source_output, source);
g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
g_object_unref (iface);
}
diff --git a/src/client/pv-stream.c b/src/client/pv-stream.c
index f93e4d1ac..bae71c38c 100644
--- a/src/client/pv-stream.c
+++ b/src/client/pv-stream.c
@@ -327,6 +327,8 @@ on_source_output_created (GObject *source_object,
&priv->source_output_sender, &priv->source_output_path, res, &error))
goto create_failed;
+ g_print ("got source-output %s %s\n", priv->source_output_sender, priv->source_output_path);
+
pv_source_output1_proxy_new (pv_context_get_connection (context),
G_DBUS_PROXY_FLAGS_NONE,
priv->source_output_sender,
diff --git a/src/client/pv-subscribe.c b/src/client/pv-subscribe.c
index 963a07768..c7ae06f6e 100644
--- a/src/client/pv-subscribe.c
+++ b/src/client/pv-subscribe.c
@@ -68,19 +68,19 @@ notify_subscription (PvSubscribe *subscribe,
if ((interface == NULL && pv_object_peek_client1 (PV_OBJECT (object))) ||
PV_IS_CLIENT1_PROXY (interface))
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
- PV_SUBSCRIPTION_FLAGS_CLIENT, g_dbus_object_get_object_path (object));
+ PV_SUBSCRIPTION_FLAGS_CLIENT, object);
}
if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_SOURCE) {
if ((interface == NULL && pv_object_peek_source1 (PV_OBJECT (object))) ||
PV_IS_SOURCE1_PROXY (interface))
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
- PV_SUBSCRIPTION_FLAGS_SOURCE, g_dbus_object_get_object_path (object));
+ PV_SUBSCRIPTION_FLAGS_SOURCE, object);
}
if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT) {
if ((interface == NULL && pv_object_peek_source_output1 (PV_OBJECT (object))) ||
PV_IS_SOURCE_OUTPUT1_PROXY (interface))
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
- PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT, g_dbus_object_get_object_path (object));
+ PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT, object);
}
}
@@ -359,7 +359,7 @@ pv_subscribe_class_init (PvSubscribeClass * klass)
3,
PV_TYPE_SUBSCRIPTION_EVENT,
PV_TYPE_SUBSCRIPTION_FLAGS,
- G_TYPE_STRING);
+ G_TYPE_DBUS_OBJECT_PROXY);
}
static void
diff --git a/src/client/pv-subscribe.h b/src/client/pv-subscribe.h
index f49e8704d..c74025c0c 100644
--- a/src/client/pv-subscribe.h
+++ b/src/client/pv-subscribe.h
@@ -41,10 +41,10 @@ typedef enum {
PV_SUBSCRIPTION_FLAGS_CLIENT = (1 << 0),
PV_SUBSCRIPTION_FLAGS_SOURCE = (1 << 1),
PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT = (1 << 2),
-
- PV_SUBSCRIPTION_FLAGS_ALL = 0xf
} PvSubscriptionFlags;
+#define PV_SUBSCRIPTION_FLAGS_ALL 0x3
+
typedef enum {
PV_SUBSCRIPTION_EVENT_NEW = 0,
PV_SUBSCRIPTION_EVENT_CHANGE = 1,
diff --git a/src/dbus/org.pulsevideo.xml b/src/dbus/org.pulsevideo.xml
index 5fe67c8aa..bd17635c5 100644
--- a/src/dbus/org.pulsevideo.xml
+++ b/src/dbus/org.pulsevideo.xml
@@ -35,14 +35,16 @@
-
-
-
+
+
+
+
+
@@ -52,7 +54,6 @@
-
diff --git a/src/modules/v4l2/pv-v4l2-source.c b/src/modules/v4l2/pv-v4l2-source.c
index 8472cab40..0348dfb5f 100644
--- a/src/modules/v4l2/pv-v4l2-source.c
+++ b/src/modules/v4l2/pv-v4l2-source.c
@@ -40,7 +40,7 @@ setup_pipeline (PvV4l2Source *source)
{
PvV4l2SourcePrivate *priv = source->priv;
- priv->pipeline = gst_parse_launch ("v4l2src ! video/x-raw,width=320,height=240,framerate=30/1 ! "
+ priv->pipeline = gst_parse_launch ("v4l2src ! video/x-raw,width=640,height=480,framerate=30/1 ! "
"pvfdpay ! multisocketsink buffers-max=2 buffers-soft-max=1 "
"recover-policy=latest sync-method=latest name=sink sync=true "
"enable-last-sample=false", NULL);
diff --git a/src/server/pv-client.c b/src/server/pv-client.c
index b456401fa..437665ed5 100644
--- a/src/server/pv-client.c
+++ b/src/server/pv-client.c
@@ -32,7 +32,7 @@ struct _PvClientPrivate
PvDaemon *daemon;
gchar *object_path;
- PvSource *source;
+ PvClient1 *client1;
GHashTable *source_outputs;
};
@@ -97,6 +97,46 @@ pv_client_set_property (GObject *_object,
}
}
+typedef struct {
+ PvClient *client;
+ GDBusMethodInvocation *invocation;
+} CreateData;
+
+static void
+on_source_output_created (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CreateData *data = user_data;
+ PvClient *client = data->client;
+ PvClientPrivate *priv = client->priv;
+ PvSource1 *source1 = PV_SOURCE1 (source_object);
+ GDBusMethodInvocation *invocation = data->invocation;
+ GError *error = NULL;
+ gchar *object_path, *name;
+
+ if (!pv_source1_call_create_source_output_finish (source1, &object_path, res, &error))
+ goto create_failed;
+
+ name = g_object_get_data (G_OBJECT (source1), "org.pulsevideo.name");
+ pv_client1_complete_create_source_output (priv->client1, invocation, name, object_path);
+ g_free (name);
+
+ g_free (data);
+
+ return;
+
+ /* ERRORS */
+create_failed:
+ {
+ g_print ("failed to get connect capture: %s", error->message);
+ g_clear_error (&error);
+ g_free (data);
+ return;
+ }
+}
+
+
static gboolean
handle_create_source_output (PvClient1 *interface,
GDBusMethodInvocation *invocation,
@@ -107,18 +147,30 @@ handle_create_source_output (PvClient1 *interface,
PvClient *client = user_data;
PvClientPrivate *priv = client->priv;
PvDaemon *daemon = priv->daemon;
- PvSource *source;
- PvSourceOutput *output;
- const gchar *object_path;
+ PvSource1 *source1;
+ GVariantBuilder builder;
+ CreateData *data;
- source = pv_daemon_get_source (daemon, arg_source);
+ source1 = pv_daemon_get_source (daemon, arg_source);
+ if (source1 == NULL) {
+ g_dbus_method_invocation_return_dbus_error (invocation,
+ "org.pulsevideo.NotFound",
+ "No source found");
+ return TRUE;
+ }
- output = pv_source_create_source_output (source, NULL, priv->object_path);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string ("hello"));
- object_path = pv_source_output_get_object_path (output);
- g_hash_table_insert (priv->source_outputs, g_strdup (object_path), output);
+ data = g_new0 (CreateData, 1);
+ data->client = client;
+ data->invocation = invocation;
- pv_client1_complete_create_source_output (interface, invocation, PV_DBUS_SERVICE, object_path);
+ pv_source1_call_create_source_output (source1,
+ g_variant_builder_end (&builder),
+ NULL,
+ on_source_output_created,
+ data);
return TRUE;
}
@@ -135,15 +187,10 @@ client_register_object (PvClient *client, const gchar *prefix)
skel = g_dbus_object_skeleton_new (name);
g_free (name);
- {
- PvClient1 *iface;
-
- iface = pv_client1_skeleton_new ();
- pv_client1_set_name (iface, "poppy");
- g_signal_connect (iface, "handle-create-source-output", (GCallback) handle_create_source_output, client);
- g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
- g_object_unref (iface);
- }
+ priv->client1 = pv_client1_skeleton_new ();
+ pv_client1_set_name (priv->client1, "poppy");
+ g_signal_connect (priv->client1, "handle-create-source-output", (GCallback) handle_create_source_output, client);
+ g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (priv->client1));
g_free (priv->object_path);
priv->object_path = pv_daemon_export_uniquely (daemon, skel);
@@ -156,7 +203,7 @@ client_unregister_object (PvClient *client)
PvDaemon *daemon = priv->daemon;
g_hash_table_unref (priv->source_outputs);
- g_clear_object (&priv->source);
+ g_clear_object (&priv->client1);
pv_daemon_unexport (daemon, priv->object_path);
g_free (priv->object_path);
diff --git a/src/server/pv-daemon.c b/src/server/pv-daemon.c
index b63f88914..946059d31 100644
--- a/src/server/pv-daemon.c
+++ b/src/server/pv-daemon.c
@@ -23,6 +23,7 @@
#include "server/pv-daemon.h"
#include "server/pv-client.h"
+#include "server/pv-source-provider.h"
#include "modules/v4l2/pv-v4l2-source.h"
#include "dbus/org-pulsevideo.h"
@@ -36,7 +37,7 @@ struct _PvDaemonPrivate
GDBusObjectManagerServer *server_manager;
GHashTable *senders;
- PvSource *source;
+ GList *sources;
};
typedef struct {
@@ -46,14 +47,74 @@ typedef struct {
GHashTable *clients;
PvSubscribe *subscribe;
+
+ GHashTable *sources;
} SenderData;
+static void
+on_subscription_event (PvSubscribe *subscribe,
+ PvSubscriptionEvent event,
+ PvSubscriptionFlags flags,
+ GDBusObjectProxy *object,
+ gpointer user_data)
+{
+ SenderData *data = user_data;
+ PvDaemon *daemon = data->daemon;
+ PvDaemonPrivate *priv = daemon->priv;
+ const gchar *object_path;
+ PvSource1 *source1;
+
+ object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
+
+ g_print ("got event %d %d %s.%s\n", event, flags, data->sender, object_path);
+
+ if (flags != PV_SUBSCRIPTION_FLAGS_SOURCE)
+ return;
+
+ source1 = pv_object_peek_source1 (PV_OBJECT (object));
+
+ switch (event) {
+ case PV_SUBSCRIPTION_EVENT_NEW:
+ {
+ g_object_set_data (G_OBJECT (source1), "org.pulsevideo.name", data->sender);
+
+ g_hash_table_insert (data->sources, g_strdup (object_path), source1);
+ priv->sources = g_list_prepend (priv->sources, source1);
+ break;
+ }
+
+ case PV_SUBSCRIPTION_EVENT_CHANGE:
+ break;
+
+ case PV_SUBSCRIPTION_EVENT_REMOVE:
+ {
+ priv->sources = g_list_remove (priv->sources, source1);
+ g_hash_table_remove (data->sources, object_path);
+ break;
+ }
+ }
+}
+
static void
client_name_appeared_handler (GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
gpointer user_data)
{
+ SenderData *data = user_data;
+
+ /* subscribe to Source events. We want to be notified when this new
+ * sender add/change/remove sources */
+ data->subscribe = pv_subscribe_new ();
+ g_object_set (data->subscribe, "service", data->sender,
+ "subscription-mask", PV_SUBSCRIPTION_FLAGS_SOURCE,
+ "connection", connection,
+ NULL);
+
+ g_signal_connect (data->subscribe,
+ "subscription-event",
+ (GCallback) on_subscription_event,
+ data);
}
static void
@@ -66,22 +127,16 @@ client_name_vanished_handler (GDBusConnection *connection,
g_print ("vanished client %s\n", name);
- g_hash_table_unref (data->clients);
g_hash_table_remove (priv->senders, data->sender);
+
+ g_hash_table_unref (data->clients);
+ g_hash_table_unref (data->sources);
+ g_object_unref (data->subscribe);
g_free (data->sender);
g_bus_unwatch_name (data->id);
g_free (data);
}
-static void
-on_subscription_event (PvSubscribe *subscribe,
- PvSubscriptionEvent event,
- PvSubscriptionFlags flags,
- const gchar *object_path)
-{
- g_print ("got event %d %d %s\n", event, flags, object_path);
-}
-
static SenderData *
sender_data_new (PvDaemon *daemon, const gchar *sender)
{
@@ -92,6 +147,7 @@ sender_data_new (PvDaemon *daemon, const gchar *sender)
data->daemon = daemon;
data->sender = g_strdup (sender);
data->clients = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ data->sources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
data->id = g_bus_watch_name_on_connection (priv->connection,
sender,
@@ -101,16 +157,6 @@ sender_data_new (PvDaemon *daemon, const gchar *sender)
data,
NULL);
- data->subscribe = pv_subscribe_new ();
- g_object_set (data->subscribe, "service", sender,
- "subscription-mask", PV_SUBSCRIPTION_FLAGS_SOURCE,
- "connection", priv->connection,
- NULL);
- g_signal_connect (data->subscribe,
- "subscription-event",
- (GCallback) on_subscription_event,
- data);
-
g_hash_table_insert (priv->senders, data->sender, data);
return data;
@@ -288,19 +334,21 @@ pv_daemon_unexport (PvDaemon *daemon, const gchar *object_path)
g_dbus_object_manager_server_unexport (daemon->priv->server_manager, object_path);
}
-PvSource *
+PvSource1 *
pv_daemon_get_source (PvDaemon *daemon, const gchar *name)
{
PvDaemonPrivate *priv;
+ PvSource1 *source;
g_return_val_if_fail (PV_IS_DAEMON (daemon), NULL);
priv = daemon->priv;
- if (priv->source == NULL) {
- priv->source = pv_v4l2_source_new ();
- pv_source_set_manager (priv->source, priv->server_manager);
- }
- return priv->source;
+ if (priv->sources == NULL)
+ return NULL;
+
+ source = priv->sources->data;
+
+ return source;
}
G_DEFINE_TYPE (PvDaemon, pv_daemon, G_TYPE_OBJECT);
diff --git a/src/server/pv-daemon.h b/src/server/pv-daemon.h
index 34a3e2550..4eddcb28b 100644
--- a/src/server/pv-daemon.h
+++ b/src/server/pv-daemon.h
@@ -23,6 +23,8 @@
#include
#include
+#include "dbus/org-pulsevideo.h"
+
G_BEGIN_DECLS
#define PV_TYPE_DAEMON (pv_daemon_get_type ())
@@ -38,7 +40,8 @@ typedef struct _PvDaemon PvDaemon;
typedef struct _PvDaemonClass PvDaemonClass;
typedef struct _PvDaemonPrivate PvDaemonPrivate;
-#include "client/pv-source.h"
+#include
+#include
/**
* PvDaemon:
@@ -61,17 +64,17 @@ struct _PvDaemonClass {
};
/* normal GObject stuff */
-GType pv_daemon_get_type (void);
+GType pv_daemon_get_type (void);
-PvDaemon * pv_daemon_new (void);
+PvDaemon * pv_daemon_new (void);
-void pv_daemon_start (PvDaemon *daemon);
-void pv_daemon_stop (PvDaemon *daemon);
+void pv_daemon_start (PvDaemon *daemon);
+void pv_daemon_stop (PvDaemon *daemon);
-gchar * pv_daemon_export_uniquely (PvDaemon *daemon, GDBusObjectSkeleton *skel);
-void pv_daemon_unexport (PvDaemon *daemon, const gchar *name);
+gchar * pv_daemon_export_uniquely (PvDaemon *daemon, GDBusObjectSkeleton *skel);
+void pv_daemon_unexport (PvDaemon *daemon, const gchar *name);
-PvSource * pv_daemon_get_source (PvDaemon *daemon, const gchar *name);
+PvSource1 * pv_daemon_get_source (PvDaemon *daemon, const gchar *name);
G_END_DECLS
diff --git a/src/server/pv-source-provider.c b/src/server/pv-source-provider.c
new file mode 100644
index 000000000..0c3fbc0ae
--- /dev/null
+++ b/src/server/pv-source-provider.c
@@ -0,0 +1,261 @@
+/* Pulsevideo
+ * Copyright (C) 2015 Wim Taymans
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "server/pv-source-provider.h"
+
+#include "dbus/org-pulsevideo.h"
+
+struct _PvSourceProviderPrivate
+{
+ PvDaemon *daemon;
+ gchar *object_path;
+
+ gchar *name;
+ gchar *path;
+};
+
+#define PV_SOURCE_PROVIDER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_SOURCE_PROVIDER, PvSourceProviderPrivate))
+
+G_DEFINE_TYPE (PvSourceProvider, pv_source_provider, G_TYPE_OBJECT);
+
+enum
+{
+ PROP_0,
+ PROP_DAEMON,
+ PROP_OBJECT_PATH,
+ PROP_NAME,
+ PROP_PATH,
+};
+
+static void
+pv_source_provider_get_property (GObject *_object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PvSourceProvider *client = PV_SOURCE_PROVIDER (_object);
+ PvSourceProviderPrivate *priv = client->priv;
+
+ switch (prop_id) {
+ case PROP_DAEMON:
+ g_value_set_object (value, priv->daemon);
+ break;
+
+ case PROP_OBJECT_PATH:
+ g_value_set_string (value, priv->object_path);
+ break;
+
+ case PROP_NAME:
+ g_value_set_string (value, priv->name);
+ break;
+
+ case PROP_PATH:
+ g_value_set_string (value, priv->path);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+pv_source_provider_set_property (GObject *_object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PvSourceProvider *client = PV_SOURCE_PROVIDER (_object);
+ PvSourceProviderPrivate *priv = client->priv;
+
+ switch (prop_id) {
+ case PROP_DAEMON:
+ priv->daemon = g_value_dup_object (value);
+ break;
+
+ case PROP_OBJECT_PATH:
+ priv->object_path = g_value_dup_string (value);
+ break;
+
+ case PROP_NAME:
+ priv->name = g_value_dup_string (value);
+ break;
+
+ case PROP_PATH:
+ priv->path = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+source_provider_register_object (PvSourceProvider *client, const gchar *prefix)
+{
+ PvSourceProviderPrivate *priv = client->priv;
+ PvDaemon *daemon = priv->daemon;
+ GDBusObjectSkeleton *skel;
+ gchar *name;
+
+ name = g_strdup_printf ("%s/source", prefix);
+ skel = g_dbus_object_skeleton_new (name);
+ g_free (name);
+
+ {
+ PvSourceProvider1 *iface;
+
+ iface = pv_source_provider1_skeleton_new ();
+ g_object_set (iface, "name", priv->name, NULL);
+ g_object_set (iface, "path", priv->path, NULL);
+ g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
+ g_object_unref (iface);
+ }
+
+ g_free (priv->object_path);
+ priv->object_path = pv_daemon_export_uniquely (daemon, skel);
+}
+
+static void
+source_provider_unregister_object (PvSourceProvider *client)
+{
+ PvSourceProviderPrivate *priv = client->priv;
+ PvDaemon *daemon = priv->daemon;
+
+ pv_daemon_unexport (daemon, priv->object_path);
+ g_free (priv->object_path);
+}
+
+static void
+pv_source_provider_finalize (GObject * object)
+{
+ PvSourceProvider *client = PV_SOURCE_PROVIDER (object);
+ PvSourceProviderPrivate *priv = client->priv;
+
+ source_provider_unregister_object (client);
+
+ g_free (priv->name);
+ g_free (priv->path);
+
+ G_OBJECT_CLASS (pv_source_provider_parent_class)->finalize (object);
+}
+
+static void
+pv_source_provider_constructed (GObject * object)
+{
+ PvSourceProvider *client = PV_SOURCE_PROVIDER (object);
+ PvSourceProviderPrivate *priv = client->priv;
+
+ source_provider_register_object (client, priv->object_path);
+
+ G_OBJECT_CLASS (pv_source_provider_parent_class)->constructed (object);
+}
+
+static void
+pv_source_provider_class_init (PvSourceProviderClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (PvSourceProviderPrivate));
+
+ gobject_class->finalize = pv_source_provider_finalize;
+ gobject_class->set_property = pv_source_provider_set_property;
+ gobject_class->get_property = pv_source_provider_get_property;
+ gobject_class->constructed = pv_source_provider_constructed;
+
+ g_object_class_install_property (gobject_class,
+ PROP_DAEMON,
+ g_param_spec_object ("daemon",
+ "Daemon",
+ "The daemon",
+ PV_TYPE_DAEMON,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class,
+ PROP_OBJECT_PATH,
+ g_param_spec_string ("object-path",
+ "Object Path",
+ "The object path",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "Name",
+ "The name of the owner",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class,
+ PROP_PATH,
+ g_param_spec_string ("path",
+ "Path",
+ "The path",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+pv_source_provider_init (PvSourceProvider * client)
+{
+ client->priv = PV_SOURCE_PROVIDER_GET_PRIVATE (client);
+}
+
+
+/**
+ * pv_source_provider_new:
+ *
+ * Make a new unconnected #PvSourceProvider
+ *
+ * Returns: a new #PvSourceProvider
+ */
+PvSourceProvider *
+pv_source_provider_new (PvDaemon *daemon,
+ const gchar *prefix,
+ const gchar *name,
+ const gchar *path)
+{
+ g_return_val_if_fail (PV_IS_DAEMON (daemon), NULL);
+ g_return_val_if_fail (g_variant_is_object_path (prefix), NULL);
+
+ return g_object_new (PV_TYPE_SOURCE_PROVIDER, "daemon", daemon, "object-path", prefix,
+ "name", name, "path", path, NULL);
+}
+
+const gchar *
+pv_source_provider_get_object_path (PvSourceProvider *client)
+{
+ PvSourceProviderPrivate *priv;
+
+ g_return_val_if_fail (PV_IS_SOURCE_PROVIDER (client), NULL);
+ priv = client->priv;
+
+ return priv->object_path;
+}
+
diff --git a/src/server/pv-source-provider.h b/src/server/pv-source-provider.h
new file mode 100644
index 000000000..17c6e9fe6
--- /dev/null
+++ b/src/server/pv-source-provider.h
@@ -0,0 +1,74 @@
+/* Pulsevideo
+ * Copyright (C) 2015 Wim Taymans
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __PV_SOURCE_PROVIDER_H__
+#define __PV_SOURCE_PROVIDER_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define PV_TYPE_SOURCE_PROVIDER (pv_source_provider_get_type ())
+#define PV_IS_SOURCE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_SOURCE_PROVIDER))
+#define PV_IS_SOURCE_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_SOURCE_PROVIDER))
+#define PV_SOURCE_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_SOURCE_PROVIDER, PvSourceProviderClass))
+#define PV_SOURCE_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_SOURCE_PROVIDER, PvSourceProvider))
+#define PV_SOURCE_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_SOURCE_PROVIDER, PvSourceProviderClass))
+#define PV_SOURCE_PROVIDER_CAST(obj) ((PvSourceProvider*)(obj))
+#define PV_SOURCE_PROVIDER_CLASS_CAST(klass) ((PvSourceProviderClass*)(klass))
+
+typedef struct _PvSourceProvider PvSourceProvider;
+typedef struct _PvSourceProviderClass PvSourceProviderClass;
+typedef struct _PvSourceProviderPrivate PvSourceProviderPrivate;
+
+#include "pv-daemon.h"
+
+
+/**
+ * PvSourceProvider:
+ *
+ * Pulsevideo source provider object class.
+ */
+struct _PvSourceProvider {
+ GObject object;
+
+ PvSourceProviderPrivate *priv;
+};
+
+/**
+ * PvSourceProviderClass:
+ *
+ * Pulsevideo source provider object class.
+ */
+struct _PvSourceProviderClass {
+ GObjectClass parent_class;
+};
+
+/* normal GObject stuff */
+GType pv_source_provider_get_type (void);
+
+PvSourceProvider * pv_source_provider_new (PvDaemon *daemon, const gchar *prefix,
+ const gchar *name, const gchar *path);
+
+const gchar * pv_source_provider_get_object_path (PvSourceProvider *client);
+
+G_END_DECLS
+
+#endif /* __PV_SOURCE_PROVIDER_H__ */
+
diff --git a/src/tests/test-client.c b/src/tests/test-client.c
index 98da7f0a2..f9d710ac0 100644
--- a/src/tests/test-client.c
+++ b/src/tests/test-client.c
@@ -22,7 +22,7 @@
#include
-#define CAPS "video/x-raw, format=(string)YUY2, width=(int)320, height=(int)240, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)30/1"
+#define CAPS "video/x-raw, format=(string)YUY2, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)30/1"
static GMainLoop *loop;
diff --git a/src/tests/test-subscribe.c b/src/tests/test-subscribe.c
index ecd1be626..c0c3e328f 100644
--- a/src/tests/test-subscribe.c
+++ b/src/tests/test-subscribe.c
@@ -25,9 +25,9 @@ static GMainLoop *loop;
static void
subscription_cb (PvContext *context, PvSubscriptionEvent type, PvSubscriptionFlags flags,
- const gchar *object_path, gpointer user_data)
+ GDBusObject *object, gpointer user_data)
{
- g_print ("got event %d %d %s\n", type, flags, object_path);
+ g_print ("got event %d %d %s\n", type, flags, g_dbus_object_get_object_path (object));
}
static void