summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/client/pv-context.c106
-rw-r--r--src/client/pv-context.h3
-rw-r--r--src/client/pv-source.c86
-rw-r--r--src/client/pv-source.h33
-rw-r--r--src/client/pv-stream.c52
-rw-r--r--src/client/pv-subscribe.c282
-rw-r--r--src/client/pv-subscribe.h11
-rw-r--r--src/daemon/main.c2
-rw-r--r--src/dbus/org.pulsevideo.xml44
-rw-r--r--src/modules/v4l2/pv-v4l2-source.c73
-rw-r--r--src/server/pv-client.c105
-rw-r--r--src/server/pv-client.h2
-rw-r--r--src/server/pv-daemon.c161
-rw-r--r--src/server/pv-daemon.h1
-rw-r--r--src/server/pv-source-provider.c2
-rw-r--r--src/tests/test-subscribe.c26
17 files changed, 603 insertions, 388 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e5770e7b..5d0788a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,6 +60,7 @@ dbuspolicy_DATA = \
###################################
enumtypesincludes = client/pv-context.h \
+ client/pv-source.h \
client/pv-stream.h \
client/pv-subscribe.h
@@ -193,7 +194,6 @@ 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-context.c b/src/client/pv-context.c
index eee417ab..90e319ef 100644
--- a/src/client/pv-context.c
+++ b/src/client/pv-context.c
@@ -40,8 +40,11 @@ struct _PvContextPrivate
PvClient1 *client;
+ PvSubscribe *internal_subscribe;
PvSubscribe *subscribe;
+ GList *sources;
+
GDBusObjectManagerServer *server_manager;
};
@@ -51,6 +54,14 @@ struct _PvContextPrivate
G_DEFINE_TYPE (PvContext, pv_context, G_TYPE_OBJECT);
+static void subscription_state (GObject *object, GParamSpec *pspec, gpointer user_data);
+static void
+subscription_cb (PvSubscribe *subscribe,
+ PvSubscriptionEvent event,
+ PvSubscriptionFlags flags,
+ GDBusProxy *object,
+ gpointer user_data);
+
enum
{
PROP_0,
@@ -223,6 +234,10 @@ pv_context_init (PvContext * context)
priv->state = PV_CONTEXT_STATE_UNCONNECTED;
priv->server_manager = g_dbus_object_manager_server_new (PV_DBUS_OBJECT_PREFIX);
+ priv->internal_subscribe = pv_subscribe_new ();
+ g_object_set (priv->internal_subscribe, "subscription-mask", PV_SUBSCRIPTION_FLAGS_ALL, NULL);
+ g_signal_connect (priv->internal_subscribe, "subscription-event", (GCallback) subscription_cb, context);
+ g_signal_connect (priv->internal_subscribe, "notify::state", (GCallback) subscription_state, context);
}
/**
@@ -302,15 +317,6 @@ on_daemon_connected (GObject *source_object,
{
PvContext *context = user_data;
PvContextPrivate *priv = context->priv;
- GError *error = NULL;
-
- priv->daemon = pv_daemon1_proxy_new_finish (res, &error);
- if (priv->daemon == NULL) {
- context_set_state (context, PV_CONTEXT_STATE_ERROR);
- g_error ("failed to get daemon: %s", error->message);
- g_clear_error (&error);
- return;
- }
context_set_state (context, PV_CONTEXT_STATE_REGISTERING);
@@ -329,6 +335,57 @@ on_daemon_connected (GObject *source_object,
}
}
+static void
+subscription_cb (PvSubscribe *subscribe,
+ PvSubscriptionEvent event,
+ PvSubscriptionFlags flags,
+ GDBusProxy *object,
+ gpointer user_data)
+{
+ PvContext *context = user_data;
+ PvContextPrivate *priv = context->priv;
+
+ g_print ("got event %d %d\n", event, flags);
+
+ switch (flags) {
+ case PV_SUBSCRIPTION_FLAGS_DAEMON:
+ priv->daemon = PV_DAEMON1 (object);
+ break;
+
+ case PV_SUBSCRIPTION_FLAGS_CLIENT:
+ break;
+
+ case PV_SUBSCRIPTION_FLAGS_SOURCE:
+ priv->sources = g_list_prepend (priv->sources, object);
+ break;
+
+ case PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT:
+ break;
+ }
+}
+
+static void
+subscription_state (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ PvContext *context = user_data;
+ PvSubscriptionState state;
+
+ g_object_get (object, "state", &state, NULL);
+
+ g_print ("got subscription state %d\n", state);
+
+ switch (state) {
+ case PV_SUBSCRIPTION_STATE_READY:
+ on_daemon_connected (NULL, NULL, context);
+ break;
+
+ default:
+ break;
+ }
+
+}
static void
on_name_appeared (GDBusConnection *connection,
@@ -343,17 +400,11 @@ on_name_appeared (GDBusConnection *connection,
g_dbus_object_manager_server_set_connection (priv->server_manager, connection);
if (priv->subscribe) {
- g_object_set (priv->subscribe, "connection", priv->connection, NULL);
- g_object_set (priv->subscribe, "service", name, NULL);
+ g_object_set (priv->subscribe, "connection", priv->connection,
+ "service", name, NULL);
}
-
- pv_daemon1_proxy_new (priv->connection,
- G_DBUS_PROXY_FLAGS_NONE,
- name,
- PV_DBUS_OBJECT_SERVER,
- NULL,
- on_daemon_connected,
- user_data);
+ g_object_set (priv->internal_subscribe, "connection", priv->connection,
+ "service", name, NULL);
}
static void
@@ -370,6 +421,8 @@ on_name_vanished (GDBusConnection *connection,
if (priv->subscribe)
g_object_set (priv->subscribe, "connection", connection, NULL);
+ g_object_set (priv->internal_subscribe, "connection", connection, NULL);
+
if (priv->flags & PV_CONTEXT_FLAGS_NOFAIL) {
context_set_state (context, PV_CONTEXT_STATE_CONNECTING);
} else {
@@ -586,3 +639,18 @@ pv_context_get_client_proxy (PvContext *context)
return G_DBUS_PROXY (context->priv->client);
}
+
+GDBusProxy *
+pv_context_find_source (PvContext *context, const gchar *name, GVariant *props)
+{
+ PvContextPrivate *priv;
+
+ g_return_val_if_fail (PV_IS_CONTEXT (context), NULL);
+ priv = context->priv;
+
+ if (priv->sources == NULL)
+ return NULL;
+
+ return priv->sources->data;
+}
+
diff --git a/src/client/pv-context.h b/src/client/pv-context.h
index e208cc7c..03f9046f 100644
--- a/src/client/pv-context.h
+++ b/src/client/pv-context.h
@@ -109,9 +109,12 @@ gboolean pv_context_register_source (PvContext *context, PvSource
gboolean pv_context_unregister_source (PvContext *context, PvSource *source);
PvContextState pv_context_get_state (PvContext *context);
+
GDBusConnection * pv_context_get_connection (PvContext *context);
GDBusProxy * pv_context_get_client_proxy (PvContext *context);
+GDBusProxy * pv_context_find_source (PvContext *context, const gchar *name, GVariant *props);
+
G_END_DECLS
diff --git a/src/client/pv-source.c b/src/client/pv-source.c
index 90de27fc..26c1971b 100644
--- a/src/client/pv-source.c
+++ b/src/client/pv-source.c
@@ -21,6 +21,7 @@
#include "client/pulsevideo.h"
#include "client/pv-source.h"
+#include "client/pv-enumtypes.h"
#include "dbus/org-pulsevideo.h"
@@ -31,10 +32,11 @@
struct _PvSourcePrivate
{
GDBusObjectManagerServer *server_manager;
+ PvSource1 *iface;
gchar *object_path;
gchar *name;
- gboolean suspended;
+ PvSourceState state;
GVariant *properties;
};
@@ -46,7 +48,7 @@ enum
PROP_MANAGER,
PROP_OBJECT_PATH,
PROP_NAME,
- PROP_SUSPENDED,
+ PROP_STATE,
PROP_PROPERTIES
};
@@ -72,8 +74,8 @@ pv_source_get_property (GObject *_object,
g_value_set_string (value, priv->name);
break;
- case PROP_SUSPENDED:
- g_value_set_boolean (value, priv->suspended);
+ case PROP_STATE:
+ g_value_set_enum (value, priv->state);
break;
case PROP_PROPERTIES:
@@ -168,20 +170,22 @@ source_register_object (PvSource *source)
PvObjectSkeleton *skel;
skel = pv_object_skeleton_new (PV_DBUS_OBJECT_SOURCE);
- {
- PvSource1 *iface;
-
- iface = pv_source1_skeleton_new ();
- g_object_set (iface, "name", priv->name,
- "suspended", priv->suspended,
- "properties", priv->properties,
- NULL);
- g_signal_connect (iface, "handle-create-source-output", (GCallback) handle_create_source_output, source);
- g_signal_connect (iface, "handle-get-capabilities", (GCallback) handle_get_capabilities, source);
- pv_object_skeleton_set_source1 (skel, iface);
- g_object_unref (iface);
- }
+
+ priv->iface = pv_source1_skeleton_new ();
+ g_object_set (priv->iface, "name", priv->name,
+ "state", priv->state,
+ "properties", priv->properties,
+ NULL);
+ g_signal_connect (priv->iface, "handle-create-source-output",
+ (GCallback) handle_create_source_output,
+ source);
+ g_signal_connect (priv->iface, "handle-get-capabilities",
+ (GCallback) handle_get_capabilities,
+ source);
+ pv_object_skeleton_set_source1 (skel, priv->iface);
+
g_dbus_object_manager_server_export_uniquely (priv->server_manager, G_DBUS_OBJECT_SKELETON (skel));
+ g_object_unref (skel);
g_free (priv->object_path);
priv->object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel)));
@@ -195,6 +199,7 @@ source_unregister_object (PvSource *source)
PvSourcePrivate *priv = source->priv;
g_dbus_object_manager_server_unexport (priv->server_manager, priv->object_path);
+ g_clear_object (&priv->iface);
}
static void
@@ -272,13 +277,14 @@ pv_source_class_init (PvSourceClass * klass)
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
- PROP_SUSPENDED,
- g_param_spec_boolean ("suspended",
- "Suspended",
- "The suspended state of the source",
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
+ PROP_STATE,
+ g_param_spec_enum ("state",
+ "State",
+ "The state of the source",
+ PV_TYPE_SOURCE_STATE,
+ PV_SOURCE_STATE_INIT,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_PROPERTIES,
@@ -339,7 +345,7 @@ pv_source_get_capabilities (PvSource *source, GVariant *props)
}
gboolean
-pv_source_suspend (PvSource *source)
+pv_source_set_state (PvSource *source, PvSourceState state)
{
PvSourceClass *klass;
gboolean res;
@@ -348,33 +354,31 @@ pv_source_suspend (PvSource *source)
klass = PV_SOURCE_GET_CLASS (source);
- if (klass->suspend)
- res = klass->suspend (source);
+ if (klass->set_state)
+ res = klass->set_state (source, state);
else
res = FALSE;
return res;
}
-gboolean
-pv_source_resume (PvSource *source)
+void
+pv_source_update_state (PvSource *source, PvSourceState state)
{
- PvSourceClass *klass;
- gboolean res;
-
- g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
-
- klass = PV_SOURCE_GET_CLASS (source);
+ PvSourcePrivate *priv;
- if (klass->resume)
- res = klass->resume (source);
- else
- res = FALSE;
+ g_return_if_fail (PV_IS_SOURCE (source));
+ priv = source->priv;
- return res;
+ if (priv->state != state) {
+ priv->state = state;
+ g_print ("source changed state %d\n", state);
+ if (priv->iface)
+ pv_source1_set_state (priv->iface, state);
+ g_object_notify (G_OBJECT (source), "state");
+ }
}
-
PvSourceOutput *
pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
{
diff --git a/src/client/pv-source.h b/src/client/pv-source.h
index 2ad46c58..e5b574cb 100644
--- a/src/client/pv-source.h
+++ b/src/client/pv-source.h
@@ -41,6 +41,26 @@ typedef struct _PvSourcePrivate PvSourcePrivate;
#define PV_SOURCE_CLASS_CAST(klass) ((PvSourceClass*)(klass))
/**
+ * PvSourceState:
+ * @PV_SOURCE_STATE_ERROR: the source is in error
+ * @PV_SOURCE_STATE_SUSPENDED: the source is suspended, the device might
+ * be closed
+ * @PV_SOURCE_STATE_INIT: the source is initializing, it opens the device
+ * and gets the device capabilities
+ * @PV_SOURCE_STATE_IDLE: the source is running but there is no active
+ * source-output
+ * @PV_SOURCE_STATE_RUNNING: the source is running.
+ *
+ * The different source states
+ */
+typedef enum {
+ PV_SOURCE_STATE_ERROR = 0,
+ PV_SOURCE_STATE_SUSPENDED = 1,
+ PV_SOURCE_STATE_INIT = 2,
+ PV_SOURCE_STATE_IDLE = 3,
+ PV_SOURCE_STATE_RUNNING = 4,
+} PvSourceState;
+/**
* PvSource:
*
* Pulsevideo source object class.
@@ -53,16 +73,19 @@ struct _PvSource {
/**
* PvSourceClass:
+ * @get_capabilities: called to get a list of supported formats from the source
+ * @set_state: called to change the current state of the source
+ * @create_source_output: called to create a new source-output object
+ * @release_source_output: called to release a source-output object
*
* Pulsevideo source object class.
*/
struct _PvSourceClass {
GObjectClass parent_class;
- GVariant * (*get_capabilities) (PvSource *source, GVariant *props);
+ GVariant * (*get_capabilities) (PvSource *source, GVariant *props);
- gboolean (*suspend) (PvSource *source);
- gboolean (*resume) (PvSource *source);
+ gboolean (*set_state) (PvSource *source, PvSourceState);
PvSourceOutput * (*create_source_output) (PvSource *source, GVariant *props, const gchar *prefix);
gboolean (*release_source_output) (PvSource *source, PvSourceOutput *output);
@@ -75,8 +98,8 @@ void pv_source_set_manager (PvSource *source, GDBusObject
GVariant * pv_source_get_capabilities (PvSource *source, GVariant *props);
-gboolean pv_source_suspend (PvSource *source);
-gboolean pv_source_resume (PvSource *source);
+gboolean pv_source_set_state (PvSource *source, PvSourceState state);
+void pv_source_update_state (PvSource *source, PvSourceState state);
PvSourceOutput * pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *prefix);
gboolean pv_source_release_source_output (PvSource *source, PvSourceOutput *output);
diff --git a/src/client/pv-stream.c b/src/client/pv-stream.c
index 84890f9c..f28dbafe 100644
--- a/src/client/pv-stream.c
+++ b/src/client/pv-stream.c
@@ -33,8 +33,8 @@ struct _PvStreamPrivate
gchar *target;
PvStreamState state;
- gchar *source_output_sender;
gchar *source_output_path;
+ PvSource1 *source;
PvSourceOutput1 *source_output;
GSocket *socket;
@@ -319,19 +319,16 @@ on_source_output_created (GObject *source_object,
PvStreamPrivate *priv = stream->priv;
PvContext *context = priv->context;
GError *error = NULL;
- PvClient1 *proxy;
- proxy = PV_CLIENT1 (pv_context_get_client_proxy (priv->context));
-
- if (!pv_client1_call_create_source_output_finish (proxy,
- &priv->source_output_sender, &priv->source_output_path, res, &error))
+ if (!pv_source1_call_create_source_output_finish (priv->source,
+ &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);
+ g_print ("got source-output %s\n", priv->source_output_path);
pv_source_output1_proxy_new (pv_context_get_connection (context),
G_DBUS_PROXY_FLAGS_NONE,
- priv->source_output_sender,
+ g_dbus_proxy_get_name (G_DBUS_PROXY (priv->source)),
priv->source_output_path,
NULL,
on_source_output1_proxy,
@@ -348,27 +345,6 @@ create_failed:
}
}
-static gboolean
-create_source_output (PvStream *stream)
-{
- PvStreamPrivate *priv = stream->priv;
- GVariantBuilder builder;
- PvClient1 *proxy;
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string ("hello"));
-
- proxy = PV_CLIENT1 (pv_context_get_client_proxy (priv->context));
-
- pv_client1_call_create_source_output (proxy,
- priv->target ? priv->target : "/", /* const gchar *arg_source */
- g_variant_builder_end (&builder), /* GVariant *arg_props */
- NULL, /* GCancellable *cancellable */
- on_source_output_created,
- stream);
- return TRUE;
-}
-
static void
on_source_output_removed (GObject *source_object,
GAsyncResult *res,
@@ -385,7 +361,6 @@ on_source_output_removed (GObject *source_object,
g_clear_error (&error);
return;
}
- g_clear_pointer (&priv->source_output_sender, g_free);
g_clear_pointer (&priv->source_output_path, g_free);
g_clear_object (&priv->source_output);
}
@@ -418,6 +393,7 @@ pv_stream_connect_capture (PvStream *stream,
PvStreamFlags flags)
{
PvStreamPrivate *priv;
+ GVariantBuilder builder;
PvContext *context;
g_return_val_if_fail (PV_IS_STREAM (stream), FALSE);
@@ -429,7 +405,21 @@ pv_stream_connect_capture (PvStream *stream,
stream_set_state (stream, PV_STREAM_STATE_CONNECTING);
- return create_source_output (stream);
+ priv->source = PV_SOURCE1 (pv_context_find_source (context, priv->target, NULL));
+ if (priv->source == NULL) {
+ g_warning ("can't find source");
+ return FALSE;
+ }
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string ("hello"));
+
+ pv_source1_call_create_source_output (priv->source,
+ g_variant_builder_end (&builder), /* GVariant *arg_props */
+ NULL, /* GCancellable *cancellable */
+ on_source_output_created,
+ stream);
+ return TRUE;
}
/**
diff --git a/src/client/pv-subscribe.c b/src/client/pv-subscribe.c
index e4cf7aff..03eac08d 100644
--- a/src/client/pv-subscribe.c
+++ b/src/client/pv-subscribe.c
@@ -26,12 +26,16 @@
struct _PvSubscribePrivate
{
+ PvSubscriptionState state;
GDBusConnection *connection;
gchar *service;
PvSubscriptionFlags subscription_mask;
GDBusObjectManager *client_manager;
+ guint pending_subscribes;
+
+ GHashTable *senders;
};
@@ -45,7 +49,8 @@ enum
PROP_0,
PROP_CONNECTION,
PROP_SERVICE,
- PROP_SUBSCRIPTION_MASK
+ PROP_SUBSCRIPTION_MASK,
+ PROP_STATE,
};
enum
@@ -56,6 +61,161 @@ enum
static guint signals[LAST_SIGNAL] = { 0 };
+
+typedef struct {
+ PvSubscribe *subscribe;
+ gchar *sender;
+ guint id;
+ PvSubscribe *sender_subscribe;
+ GList *clients;
+} SenderData;
+
+static void
+notify_subscription (PvSubscribe *subscribe,
+ GDBusObject *object,
+ GDBusInterface *interface,
+ PvSubscriptionEvent event);
+
+static void
+on_sender_subscription_event (PvSubscribe *sender_subscribe,
+ PvSubscriptionEvent event,
+ PvSubscriptionFlags flags,
+ GDBusProxy *object,
+ gpointer user_data)
+{
+ SenderData *data = user_data;
+ PvSubscribe *subscribe = data->subscribe;
+
+ g_signal_emit (subscribe,
+ signals[SIGNAL_SUBSCRIPTION_EVENT],
+ 0,
+ event,
+ flags,
+ object);
+}
+
+static void
+subscription_set_state (PvSubscribe *subscribe, PvSubscriptionState state)
+{
+ PvSubscribePrivate *priv = subscribe->priv;
+
+ if (state != priv->state) {
+ priv->state = state;
+ g_object_notify (G_OBJECT (subscribe), "state");
+ }
+}
+
+static void
+on_sender_subscription_state (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ SenderData *data = user_data;
+ PvSubscribe *subscribe = data->subscribe;
+ PvSubscribePrivate *priv = subscribe->priv;
+ PvSubscriptionState state;
+
+ g_object_get (object, "state", &state, NULL);
+
+ switch (state) {
+ case PV_SUBSCRIPTION_STATE_READY:
+ if (--priv->pending_subscribes == 0)
+ subscription_set_state (subscribe, state);
+ break;
+
+ case PV_SUBSCRIPTION_STATE_ERROR:
+ subscription_set_state (subscribe, state);
+ break;
+
+ default:
+ 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 and outputs */
+ data->sender_subscribe = pv_subscribe_new ();
+ g_object_set (data->sender_subscribe, "service", data->sender,
+ "subscription-mask", PV_SUBSCRIPTION_FLAGS_ALL,
+ "connection", connection,
+ NULL);
+
+ g_signal_connect (data->sender_subscribe,
+ "subscription-event",
+ (GCallback) on_sender_subscription_event,
+ data);
+ g_signal_connect (data->sender_subscribe,
+ "notify::state",
+ (GCallback) on_sender_subscription_state,
+ data);
+}
+
+static void
+remove_client (PvClient1 *client, SenderData *data)
+{
+ g_signal_emit (data->subscribe,
+ signals[SIGNAL_SUBSCRIPTION_EVENT],
+ 0,
+ PV_SUBSCRIPTION_EVENT_REMOVE,
+ PV_SUBSCRIPTION_FLAGS_CLIENT,
+ client);
+}
+
+static void
+client_name_vanished_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ SenderData *data = user_data;
+ PvSubscribePrivate *priv = data->subscribe->priv;
+
+ g_print ("vanished client %s\n", name);
+
+ g_list_foreach (data->clients, (GFunc) remove_client, data);
+
+ g_hash_table_remove (priv->senders, data->sender);
+
+ if (data->sender_subscribe)
+ g_object_unref (data->sender_subscribe);
+ g_free (data->sender);
+ g_bus_unwatch_name (data->id);
+ g_free (data);
+}
+
+static SenderData *
+sender_data_new (PvSubscribe *subscribe, const gchar *sender)
+{
+ PvSubscribePrivate *priv = subscribe->priv;
+ SenderData *data;
+
+ g_print ("watch name %s\n", sender);
+
+ data = g_new0 (SenderData, 1);
+ data->subscribe = subscribe;
+ data->sender = g_strdup (sender);
+
+ data->id = g_bus_watch_name_on_connection (priv->connection,
+ sender,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ client_name_appeared_handler,
+ client_name_vanished_handler,
+ data,
+ NULL);
+
+ g_hash_table_insert (priv->senders, data->sender, data);
+ priv->pending_subscribes++;
+
+ return data;
+}
+
static void
notify_subscription (PvSubscribe *subscribe,
GDBusObject *object,
@@ -64,29 +224,81 @@ notify_subscription (PvSubscribe *subscribe,
{
PvSubscribePrivate *priv = subscribe->priv;
- if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_CLIENT) {
- if ((interface == NULL && pv_object_peek_client1 (PV_OBJECT (object))) ||
- PV_IS_CLIENT1_PROXY (interface))
+ if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_DAEMON) {
+ PvDaemon1 *daemon;
+
+ if (interface == NULL)
+ daemon = pv_object_peek_daemon1 (PV_OBJECT (object));
+ else if (PV_IS_DAEMON1_PROXY (interface))
+ daemon = PV_DAEMON1 (interface);
+ else
+ daemon = NULL;
+
+ if (daemon) {
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
- PV_SUBSCRIPTION_FLAGS_CLIENT, object);
+ PV_SUBSCRIPTION_FLAGS_DAEMON, daemon);
+ }
}
- if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_SOURCE_PROVIDER) {
- if ((interface == NULL && pv_object_peek_source_provider1 (PV_OBJECT (object))) ||
- PV_IS_SOURCE_PROVIDER1_PROXY (interface))
- g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
- PV_SUBSCRIPTION_FLAGS_SOURCE_PROVIDER, object);
+ if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_CLIENT) {
+ PvClient1 *client;
+
+ if (interface == NULL)
+ client = pv_object_peek_client1 (PV_OBJECT (object));
+ else if (PV_IS_CLIENT1_PROXY (interface))
+ client = PV_CLIENT1 (interface);
+ else
+ client = NULL;
+
+ if (client) {
+ const gchar *sender;
+ SenderData *data;
+
+ sender = pv_client1_get_name (client);
+
+ data = g_hash_table_lookup (priv->senders, sender);
+ if (data == NULL && event != PV_SUBSCRIPTION_EVENT_REMOVE) {
+ data = sender_data_new (subscribe, sender);
+ }
+ if (data) {
+ if (event == PV_SUBSCRIPTION_EVENT_NEW)
+ data->clients = g_list_prepend (data->clients, client);
+ else if (event == PV_SUBSCRIPTION_EVENT_REMOVE)
+ data->clients = g_list_remove (data->clients, client);
+
+ g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
+ PV_SUBSCRIPTION_FLAGS_CLIENT, client);
+ }
+ }
}
if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_SOURCE) {
- if ((interface == NULL && pv_object_peek_source1 (PV_OBJECT (object))) ||
- PV_IS_SOURCE1_PROXY (interface))
+ PvSource1 *source;
+
+ if (interface == NULL)
+ source = pv_object_peek_source1 (PV_OBJECT (object));
+ else if (PV_IS_SOURCE1_PROXY (interface))
+ source = PV_SOURCE1 (interface);
+ else
+ source = NULL;
+
+ if (source) {
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
- PV_SUBSCRIPTION_FLAGS_SOURCE, object);
+ PV_SUBSCRIPTION_FLAGS_SOURCE, source);
+ }
}
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))
+ PvSourceOutput1 *output;
+
+ if (interface == NULL)
+ output = pv_object_peek_source_output1 (PV_OBJECT (object));
+ else if PV_IS_SOURCE_OUTPUT1_PROXY (interface)
+ output = PV_SOURCE_OUTPUT1 (interface);
+ else
+ output = NULL;
+
+ if (output) {
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
- PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT, object);
+ PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT, output);
+ }
}
}
@@ -184,13 +396,20 @@ on_client_manager_ready (GObject *source_object,
if (priv->client_manager == NULL)
goto manager_error;
+ g_print ("client manager %s %s\n",
+ g_dbus_object_manager_client_get_name (G_DBUS_OBJECT_MANAGER_CLIENT (priv->client_manager)),
+ g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (priv->client_manager)));
+
+ connect_client_signals (subscribe);
+
objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (priv->client_manager));
for (walk = objects; walk ; walk = g_list_next (walk)) {
on_client_manager_object_added (G_DBUS_OBJECT_MANAGER (priv->client_manager),
walk->data,
subscribe);
}
- connect_client_signals (subscribe);
+ if (--priv->pending_subscribes == 0)
+ subscription_set_state (subscribe, PV_SUBSCRIPTION_STATE_READY);
return;
@@ -199,6 +418,7 @@ manager_error:
{
g_warning ("could not create client manager: %s", error->message);
g_clear_error (&error);
+ subscription_set_state (subscribe, PV_SUBSCRIPTION_STATE_ERROR);
return;
}
}
@@ -208,6 +428,9 @@ install_subscription (PvSubscribe *subscribe)
{
PvSubscribePrivate *priv = subscribe->priv;
+ subscription_set_state (subscribe, PV_SUBSCRIPTION_STATE_CONNECTING);
+
+ g_print ("new client manager for %s\n", priv->service);
pv_object_manager_client_new (priv->connection,
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
priv->service,
@@ -215,6 +438,7 @@ install_subscription (PvSubscribe *subscribe)
NULL,
on_client_manager_ready,
subscribe);
+ priv->pending_subscribes++;
}
static void
@@ -223,6 +447,7 @@ uninstall_subscription (PvSubscribe *subscribe)
PvSubscribePrivate *priv = subscribe->priv;
g_clear_object (&priv->client_manager);
+ subscription_set_state (subscribe, PV_SUBSCRIPTION_STATE_UNCONNECTED);
}
static void
@@ -247,6 +472,10 @@ pv_subscribe_get_property (GObject *_object,
g_value_set_flags (value, priv->subscription_mask);
break;
+ case PROP_STATE:
+ g_value_set_enum (value, priv->state);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (subscribe, prop_id, pspec);
break;
@@ -296,6 +525,7 @@ pv_subscribe_finalize (GObject * object)
g_free (priv->service);
g_object_unref (priv->client_manager);
+ g_hash_table_unref (priv->senders);
G_OBJECT_CLASS (pv_subscribe_parent_class)->finalize (object);
}
@@ -353,6 +583,20 @@ pv_subscribe_class_init (PvSubscribeClass * klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
+ * PvSubscribe:state
+ *
+ * The state of the subscription
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_STATE,
+ g_param_spec_enum ("state",
+ "State",
+ "The state",
+ PV_TYPE_SUBSCRIPTION_STATE,
+ PV_SUBSCRIPTION_STATE_UNCONNECTED,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+ /**
* PvSubscribe:subscription-event
* @subscribe: The #PvSubscribe emitting the signal.
* @event: A #PvSubscriptionEvent
@@ -372,7 +616,7 @@ pv_subscribe_class_init (PvSubscribeClass * klass)
3,
PV_TYPE_SUBSCRIPTION_EVENT,
PV_TYPE_SUBSCRIPTION_FLAGS,
- G_TYPE_DBUS_OBJECT_PROXY);
+ G_TYPE_DBUS_PROXY);
}
static void
@@ -381,6 +625,8 @@ pv_subscribe_init (PvSubscribe * subscribe)
PvSubscribePrivate *priv = subscribe->priv = PV_SUBSCRIBE_GET_PRIVATE (subscribe);
priv->service = g_strdup (PV_DBUS_SERVICE);
+ priv->senders = g_hash_table_new (g_str_hash, g_str_equal);
+ priv->state = PV_SUBSCRIPTION_STATE_UNCONNECTED;
}
/**
diff --git a/src/client/pv-subscribe.h b/src/client/pv-subscribe.h
index d1a5278e..8b6038b9 100644
--- a/src/client/pv-subscribe.h
+++ b/src/client/pv-subscribe.h
@@ -38,8 +38,15 @@ typedef struct _PvSubscribeClass PvSubscribeClass;
typedef struct _PvSubscribePrivate PvSubscribePrivate;
typedef enum {
- PV_SUBSCRIPTION_FLAGS_CLIENT = (1 << 0),
- PV_SUBSCRIPTION_FLAGS_SOURCE_PROVIDER = (1 << 1),
+ PV_SUBSCRIPTION_STATE_UNCONNECTED = 0,
+ PV_SUBSCRIPTION_STATE_CONNECTING = 1,
+ PV_SUBSCRIPTION_STATE_READY = 2,
+ PV_SUBSCRIPTION_STATE_ERROR = 3,
+} PvSubscriptionState;
+
+typedef enum {
+ PV_SUBSCRIPTION_FLAGS_DAEMON = (1 << 0),
+ PV_SUBSCRIPTION_FLAGS_CLIENT = (1 << 1),
PV_SUBSCRIPTION_FLAGS_SOURCE = (1 << 2),
PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT = (1 << 3),
} PvSubscriptionFlags;
diff --git a/src/daemon/main.c b/src/daemon/main.c
index cb0fbbfe..3fc4749f 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -38,7 +38,7 @@ main (gint argc, gchar *argv[])
daemon = pv_daemon_new ();
source = pv_v4l2_source_new();
- pv_daemon_add_source (daemon, source);
+ //pv_daemon_add_source (daemon, source);
pv_daemon_start (daemon);
g_main_loop_run (loop);
diff --git a/src/dbus/org.pulsevideo.xml b/src/dbus/org.pulsevideo.xml
index 4e6de9fe..86b85996 100644
--- a/src/dbus/org.pulsevideo.xml
+++ b/src/dbus/org.pulsevideo.xml
@@ -46,25 +46,6 @@
<property name='Name' type='s' access='read' />
<!-- Name: Properties of the client -->
<property name='Properties' type='a{sv}' access='read' />
- <!-- CreateSourceOutput:
- @source: the name of a source or an empty string
- @props: properties to use
- @sender: the result sender of the output
- @output: the result output object
-
- This method requests an output from @source with given @props.
- @source can be the empty string, in which case the server will
- select a good source.
-
- @sender and @output contain the unique name and object of the
- owner of the source.
- -->
- <method name='CreateSourceOutput'>
- <arg type='s' name='source' direction='in'/>
- <arg type='a{sv}' name='props' direction='in'/>
- <arg type='s' name='sender' direction='out'/>
- <arg type='o' name='output' direction='out'/>
- </method>
<!-- Disconnect:
Disconnect the client from the server.
@@ -99,20 +80,6 @@
</interface>
<!--
- org.pulsevideo.SourceProvider1:
- @short_description: Interface for source provider
-
- This interface lists the unique name and path of a
- source
- -->
- <interface name='org.pulsevideo.SourceProvider1'>
- <!-- Name: unique name of the provider -->
- <property name='Name' type='s' access='read' />
- <!-- Path: object path of the source -->
- <property name='Path' type='o' access='read' />
- </interface>
-
- <!--
org.pulsevideo.Source1:
@short_description: Main source interface
@@ -123,8 +90,15 @@
<property name='Name' type='s' access='read' />
<!-- Properties: extra source properties -->
<property name='Properties' type='a{sv}' access='read' />
- <!-- Suspended: if the source is suspended -->
- <property name='Suspended' type='b' access='read' />
+ <!-- state: state of the source
+ 0 = the source is in error
+ 1 = the source is initializing
+ 2 = the source is suspended, this means the device is closed
+ 3 = the source is idle, this means the device is opened but
+ no source-output is consuming the data
+ 4 = the source is running
+ -->
+ <property name='State' type='u' access='read' />
<!-- GetCapabilities:
@props: input properties
@caps: result capabilities
diff --git a/src/modules/v4l2/pv-v4l2-source.c b/src/modules/v4l2/pv-v4l2-source.c
index 5f51e829..3c18224e 100644
--- a/src/modules/v4l2/pv-v4l2-source.c
+++ b/src/modules/v4l2/pv-v4l2-source.c
@@ -28,6 +28,7 @@
struct _PvV4l2SourcePrivate
{
GstElement *pipeline;
+ GstElement *src;
GstElement *sink;
GSocket *socket;
@@ -40,13 +41,70 @@ setup_pipeline (PvV4l2Source *source)
{
PvV4l2SourcePrivate *priv = source->priv;
- 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);
+ priv->pipeline = gst_parse_launch ("v4l2src name=src ! "
+ "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);
priv->sink = gst_bin_get_by_name (GST_BIN (priv->pipeline), "sink");
+ priv->src = gst_bin_get_by_name (GST_BIN (priv->pipeline), "src");
+}
- gst_element_set_state (priv->pipeline, GST_STATE_READY);
+static void
+collect_capabilities (PvSource * source)
+{
+ PvV4l2SourcePrivate *priv = PV_V4L2_SOURCE (source)->priv;
+ GstCaps *res;
+ GstQuery *query;
+
+ query = gst_query_new_caps (NULL);
+ gst_element_query (priv->src, query);
+ gst_query_parse_caps_result (query, &res);
+ g_print ("%s\n", gst_caps_to_string (res));
+ gst_query_unref (query);
+}
+
+static gboolean
+v4l2_set_state (PvSource *source, PvSourceState state)
+{
+ PvV4l2SourcePrivate *priv = PV_V4L2_SOURCE (source)->priv;
+
+ switch (state) {
+ case PV_SOURCE_STATE_SUSPENDED:
+ gst_element_set_state (priv->pipeline, GST_STATE_NULL);
+ break;
+
+ case PV_SOURCE_STATE_INIT:
+ gst_element_set_state (priv->pipeline, GST_STATE_READY);
+ collect_capabilities (source);
+ break;
+
+ case PV_SOURCE_STATE_IDLE:
+ gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
+ break;
+
+ case PV_SOURCE_STATE_RUNNING:
+ gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
+ break;
+
+ case PV_SOURCE_STATE_ERROR:
+ break;
+ }
+ pv_source_update_state (source, state);
+ return TRUE;
+}
+
+static GVariant *
+v4l2_get_capabilities (PvSource *source, GVariant *props)
+{
+ return NULL;
}
static void
@@ -80,10 +138,13 @@ on_socket_notify (GObject *gobject,
static PvSourceOutput *
v4l2_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
{
+ PvV4l2SourcePrivate *priv = PV_V4L2_SOURCE (source)->priv;
PvSourceOutput *output;
output = PV_SOURCE_CLASS (pv_v4l2_source_parent_class)->create_source_output (source, props, prefix);
+ gst_element_set_state (priv->pipeline, GST_STATE_READY);
+
g_signal_connect (output, "notify::socket", (GCallback) on_socket_notify, source);
return output;
@@ -111,6 +172,8 @@ pv_v4l2_source_class_init (PvV4l2SourceClass * klass)
gobject_class->finalize = v4l2_source_finalize;
+ source_class->get_capabilities = v4l2_get_capabilities;
+ source_class->set_state = v4l2_set_state;
source_class->create_source_output = v4l2_create_source_output;
source_class->release_source_output = v4l2_release_source_output;
}
diff --git a/src/server/pv-client.c b/src/server/pv-client.c
index 38ec8227..a67cad94 100644
--- a/src/server/pv-client.c
+++ b/src/server/pv-client.c
@@ -30,6 +30,7 @@
struct _PvClientPrivate
{
PvDaemon *daemon;
+ gchar *sender;
gchar *object_path;
PvClient1 *client1;
@@ -46,6 +47,7 @@ enum
{
PROP_0,
PROP_DAEMON,
+ PROP_SENDER,
PROP_OBJECT_PATH,
};
@@ -63,6 +65,10 @@ pv_client_get_property (GObject *_object,
g_value_set_object (value, priv->daemon);
break;
+ case PROP_SENDER:
+ g_value_set_string (value, priv->sender);
+ break;
+
case PROP_OBJECT_PATH:
g_value_set_string (value, priv->object_path);
break;
@@ -87,6 +93,10 @@ pv_client_set_property (GObject *_object,
priv->daemon = g_value_dup_object (value);
break;
+ case PROP_SENDER:
+ priv->sender = g_value_dup_string (value);
+ break;
+
case PROP_OBJECT_PATH:
priv->object_path = g_value_dup_string (value);
break;
@@ -97,84 +107,6 @@ 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,
- const gchar *arg_source,
- GVariant *arg_properties,
- gpointer user_data)
-{
- PvClient *client = user_data;
- PvClientPrivate *priv = client->priv;
- PvDaemon *daemon = priv->daemon;
- PvSource1 *source1;
- GVariantBuilder builder;
- CreateData *data;
-
- 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;
- }
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string ("hello"));
-
- data = g_new0 (CreateData, 1);
- data->client = client;
- data->invocation = invocation;
-
- pv_source1_call_create_source_output (source1,
- g_variant_builder_end (&builder),
- NULL,
- on_source_output_created,
- data);
-
- return TRUE;
-}
-
static void
client_register_object (PvClient *client, const gchar *prefix)
{
@@ -188,8 +120,7 @@ client_register_object (PvClient *client, const gchar *prefix)
g_free (name);
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);
+ pv_client1_set_name (priv->client1, priv->sender);
pv_object_skeleton_set_client1 (skel, priv->client1);
g_free (priv->object_path);
@@ -253,6 +184,16 @@ pv_client_class_init (PvClientClass * klass)
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
+ PROP_SENDER,
+ g_param_spec_string ("sender",
+ "Sender",
+ "The sender",
+ NULL,
+ 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",
@@ -282,12 +223,12 @@ pv_client_init (PvClient * client)
* Returns: a new #PvClient
*/
PvClient *
-pv_client_new (PvDaemon * daemon, const gchar *prefix)
+pv_client_new (PvDaemon * daemon, const gchar *sender, const gchar *prefix)
{
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_CLIENT, "daemon", daemon, "object-path", prefix, NULL);
+ return g_object_new (PV_TYPE_CLIENT, "daemon", daemon, "sender", sender, "object-path", prefix, NULL);
}
/**
diff --git a/src/server/pv-client.h b/src/server/pv-client.h
index 41bac328..58387070 100644
--- a/src/server/pv-client.h
+++ b/src/server/pv-client.h
@@ -62,7 +62,7 @@ struct _PvClientClass {
/* normal GObject stuff */
GType pv_client_get_type (void);
-PvClient * pv_client_new (PvDaemon *daemon, const gchar *prefix);
+PvClient * pv_client_new (PvDaemon *daemon, const gchar *sender, const gchar *prefix);
const gchar * pv_client_get_object_path (PvClient *client);
diff --git a/src/server/pv-daemon.c b/src/server/pv-daemon.c
index a662e321..2b01aa6b 100644
--- a/src/server/pv-daemon.c
+++ b/src/server/pv-daemon.c
@@ -23,7 +23,6 @@
#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"
@@ -37,86 +36,32 @@ struct _PvDaemonPrivate
GDBusObjectManagerServer *server_manager;
PvSubscribe *subscribe;
- GHashTable *senders;
+ GHashTable *clients;
GList *sources;
};
-typedef struct {
- PvDaemon *daemon;
- gchar *sender;
- guint id;
-
- GHashTable *clients;
- PvSubscribe *subscribe;
-
- GHashTable *sources;
-} SenderData;
-
static void
on_server_subscription_event (PvSubscribe *subscribe,
PvSubscriptionEvent event,
PvSubscriptionFlags flags,
- GDBusObjectProxy *object,
+ GDBusProxy *object,
gpointer user_data)
{
PvDaemon *daemon = user_data;
PvDaemonPrivate *priv = daemon->priv;
- const gchar *object_path;
- PvSource1 *source1;
- gchar *service;
-
- if (flags != PV_SUBSCRIPTION_FLAGS_SOURCE)
- return;
-
- object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
-
- g_object_get (subscribe, "service", &service, NULL);
- g_print ("got event %d %d %s.%s\n", event, flags, service, object_path);
-
- 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", service);
- 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);
- break;
- }
- }
-}
-
-static void
-on_sender_subscription_event (PvSubscribe *subscribe,
- PvSubscriptionEvent event,
- PvSubscriptionFlags flags,
- GDBusObjectProxy *object,
- gpointer user_data)
-{
- SenderData *data = user_data;
- PvDaemon *daemon = data->daemon;
- const gchar *object_path;
+ const gchar *name, *object_path;
- on_server_subscription_event (subscribe, event, flags, object, daemon);
+ name = g_dbus_proxy_get_name (object);
+ object_path = g_dbus_proxy_get_object_path (object);
- object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
+ g_print ("got event %d %d %s:%s\n", event, flags, name, object_path);
switch (event) {
case PV_SUBSCRIPTION_EVENT_NEW:
{
- PvSourceProvider *provider;
-
- provider = pv_source_provider_new (daemon, PV_DBUS_OBJECT_PREFIX, data->sender,
- object_path);
- g_hash_table_insert (data->sources, g_strdup (object_path), provider);
+ if (PV_IS_SOURCE1 (object)) {
+ priv->sources = g_list_prepend (priv->sources, object);
+ }
break;
}
@@ -125,80 +70,16 @@ on_sender_subscription_event (PvSubscribe *subscribe,
case PV_SUBSCRIPTION_EVENT_REMOVE:
{
- g_hash_table_remove (data->sources, object_path);
+ if (PV_IS_SOURCE1 (object)) {
+ priv->sources = g_list_remove (priv->sources, object);
+ } else if (PV_IS_CLIENT1 (object)) {
+ g_hash_table_remove (priv->clients, 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_sender_subscription_event,
- data);
-}
-
-static void
-client_name_vanished_handler (GDBusConnection *connection,
- const gchar *name,
- gpointer user_data)
-{
- SenderData *data = user_data;
- PvDaemonPrivate *priv = data->daemon->priv;
-
- g_print ("vanished client %s\n", name);
-
- 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 SenderData *
-sender_data_new (PvDaemon *daemon, const gchar *sender)
-{
- PvDaemonPrivate *priv = daemon->priv;
- SenderData *data;
-
- data = g_new0 (SenderData, 1);
- 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,
- G_BUS_NAME_WATCHER_FLAGS_NONE,
- client_name_appeared_handler,
- client_name_vanished_handler,
- data,
- NULL);
-
- g_hash_table_insert (priv->senders, data->sender, data);
-
- return data;
-}
-
static gboolean
handle_connect_client (PvDaemon1 *interface,
GDBusMethodInvocation *invocation,
@@ -209,20 +90,15 @@ handle_connect_client (PvDaemon1 *interface,
PvDaemonPrivate *priv = daemon->priv;
PvClient *client;
const gchar *sender, *object_path;
- SenderData *data;
sender = g_dbus_method_invocation_get_sender (invocation);
g_print ("connect client %s\n", sender);
- data = g_hash_table_lookup (priv->senders, sender);
- if (data == NULL) {
- data = sender_data_new (daemon, sender);
- }
- client = pv_client_new (daemon, PV_DBUS_OBJECT_PREFIX);
+ client = pv_client_new (daemon, sender, PV_DBUS_OBJECT_PREFIX);
object_path = pv_client_get_object_path (client);
- g_hash_table_insert (data->clients, g_strdup (object_path), client);
+ g_hash_table_insert (priv->clients, g_strdup (object_path), client);
pv_daemon1_complete_connect_client (interface, invocation, object_path);
@@ -272,7 +148,7 @@ name_acquired_handler (GDBusConnection *connection,
GDBusObjectManagerServer *manager = priv->server_manager;
g_object_set (priv->subscribe, "service", PV_DBUS_SERVICE,
- "subscription-mask", PV_SUBSCRIPTION_FLAGS_SOURCE,
+ "subscription-mask", PV_SUBSCRIPTION_FLAGS_ALL,
"connection", connection,
NULL);
@@ -461,7 +337,6 @@ pv_daemon_finalize (GObject * object)
PvDaemonPrivate *priv = daemon->priv;
g_clear_object (&priv->server_manager);
- g_hash_table_unref (priv->senders);
pv_daemon_stop (daemon);
G_OBJECT_CLASS (pv_daemon_parent_class)->finalize (object);
@@ -482,8 +357,8 @@ pv_daemon_init (PvDaemon * daemon)
{
PvDaemonPrivate *priv = daemon->priv = PV_DAEMON_GET_PRIVATE (daemon);
- priv->senders = g_hash_table_new (g_str_hash, g_str_equal);
priv->server_manager = g_dbus_object_manager_server_new (PV_DBUS_OBJECT_PREFIX);
+ priv->clients = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
priv->subscribe = pv_subscribe_new ();
g_signal_connect (priv->subscribe,
diff --git a/src/server/pv-daemon.h b/src/server/pv-daemon.h
index bdb9c947..3be38392 100644
--- a/src/server/pv-daemon.h
+++ b/src/server/pv-daemon.h
@@ -41,7 +41,6 @@ typedef struct _PvDaemonClass PvDaemonClass;
typedef struct _PvDaemonPrivate PvDaemonPrivate;
#include <client/pv-source.h>
-#include <server/pv-source-provider.h>
/**
* PvDaemon:
diff --git a/src/server/pv-source-provider.c b/src/server/pv-source-provider.c
index 2350c8e7..c377be4f 100644
--- a/src/server/pv-source-provider.c
+++ b/src/server/pv-source-provider.c
@@ -116,7 +116,7 @@ source_provider_register_object (PvSourceProvider *client, const gchar *prefix)
PvObjectSkeleton *skel;
gchar *name;
- name = g_strdup_printf ("%s/source", prefix);
+ name = g_strdup_printf ("%s/source_provider", prefix);
skel = pv_object_skeleton_new (name);
g_free (name);
diff --git a/src/tests/test-subscribe.c b/src/tests/test-subscribe.c
index c0c3e328..a87b813c 100644
--- a/src/tests/test-subscribe.c
+++ b/src/tests/test-subscribe.c
@@ -24,10 +24,32 @@
static GMainLoop *loop;
static void
+dump_object (GDBusProxy *proxy)
+{
+
+}
+
+static void
subscription_cb (PvContext *context, PvSubscriptionEvent type, PvSubscriptionFlags flags,
- GDBusObject *object, gpointer user_data)
+ GDBusProxy *object, gpointer user_data)
{
- g_print ("got event %d %d %s\n", type, flags, g_dbus_object_get_object_path (object));
+ g_print ("got event %d %d %s:%s\n", type, flags,
+ g_dbus_proxy_get_name (object),
+ g_dbus_proxy_get_object_path (object));
+
+ switch (type) {
+ case PV_SUBSCRIPTION_EVENT_NEW:
+ dump_object (object);
+ break;
+
+ case PV_SUBSCRIPTION_EVENT_CHANGE:
+ dump_object (object);
+ break;
+
+ case PV_SUBSCRIPTION_EVENT_REMOVE:
+ g_print ("object removed %s\n", g_dbus_proxy_get_object_path (object));
+ break;
+ }
}
static void