diff --git a/src/client/pv-context.c b/src/client/pv-context.c index 66f4918d3..ee111a3bb 100644 --- a/src/client/pv-context.c +++ b/src/client/pv-context.c @@ -455,6 +455,49 @@ pv_context_connect (PvContext *context, PvContextFlags flags) return TRUE; } +static void +on_client_disconnected (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + PvContext *context = user_data; + PvContextPrivate *priv = context->priv; + GError *error = NULL; + + if (!pv_client1_call_disconnect_finish (priv->client, res, &error)) { + context_set_state (context, PV_CONTEXT_STATE_ERROR); + g_error ("failed to disconnect client: %s", error->message); + g_clear_error (&error); + return; + } + context_set_state (context, PV_CONTEXT_STATE_UNCONNECTED); +} + +/** + * pv_context_disconnect: + * @context: a #PvContext + * + * Disonnect from the daemon. + * + * Returns: %TRUE on success. + */ +gboolean +pv_context_disconnect (PvContext *context) +{ + PvContextPrivate *priv; + + g_return_val_if_fail (PV_IS_CONTEXT (context), FALSE); + + priv = context->priv; + g_return_val_if_fail (priv->client != NULL, FALSE); + + pv_client1_call_disconnect (priv->client, + NULL, /* GCancellable *cancellable */ + on_client_disconnected, + context); + return TRUE; +} + gboolean pv_context_register_source (PvContext *context, PvSource *source) { diff --git a/src/client/pv-context.h b/src/client/pv-context.h index 1c2781c0e..e8cadeb9d 100644 --- a/src/client/pv-context.h +++ b/src/client/pv-context.h @@ -103,6 +103,7 @@ PvContext * pv_context_new (const gchar *name, GVariant gboolean pv_context_set_subscribe (PvContext *context, PvSubscribe *subscribe); gboolean pv_context_connect (PvContext *context, PvContextFlags flags); +gboolean pv_context_disconnect (PvContext *context); gboolean pv_context_register_source (PvContext *context, PvSource *source); gboolean pv_context_unregister_source (PvContext *context, PvSource *source); diff --git a/src/client/pv-source-output.c b/src/client/pv-source-output.c index 64ef9f7c1..88c8729b4 100644 --- a/src/client/pv-source-output.c +++ b/src/client/pv-source-output.c @@ -174,11 +174,11 @@ static void output_register_object (PvSourceOutput *output, const gchar *prefix) { PvSourceOutputPrivate *priv = output->priv; - GDBusObjectSkeleton *skel; + PvObjectSkeleton *skel; gchar *name; name = g_strdup_printf ("%s/output", prefix); - skel = g_dbus_object_skeleton_new (name); + skel = pv_object_skeleton_new (name); g_free (name); { @@ -188,10 +188,10 @@ output_register_object (PvSourceOutput *output, const gchar *prefix) g_signal_connect (iface, "handle-start", (GCallback) handle_start, output); g_signal_connect (iface, "handle-stop", (GCallback) handle_stop, output); g_signal_connect (iface, "handle-remove", (GCallback) handle_remove, output); - g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface)); + pv_object_skeleton_set_source_output1 (skel, iface); g_object_unref (iface); } - g_dbus_object_manager_server_export_uniquely (priv->server_manager, skel); + g_dbus_object_manager_server_export_uniquely (priv->server_manager, G_DBUS_OBJECT_SKELETON (skel)); g_free (priv->object_path); priv->object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel))); diff --git a/src/client/pv-source.c b/src/client/pv-source.c index 7071372dc..5c7f68df4 100644 --- a/src/client/pv-source.c +++ b/src/client/pv-source.c @@ -118,18 +118,18 @@ static void source_register_object (PvSource *source) { PvSourcePrivate *priv = source->priv; - GDBusObjectSkeleton *skel; + PvObjectSkeleton *skel; - skel = g_dbus_object_skeleton_new (PV_DBUS_OBJECT_SOURCE); + skel = pv_object_skeleton_new (PV_DBUS_OBJECT_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)); + pv_object_skeleton_set_source1 (skel, iface); g_object_unref (iface); } - g_dbus_object_manager_server_export_uniquely (priv->server_manager, skel); + g_dbus_object_manager_server_export_uniquely (priv->server_manager, G_DBUS_OBJECT_SKELETON (skel)); g_free (priv->object_path); priv->object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel))); diff --git a/src/client/pv-subscribe.c b/src/client/pv-subscribe.c index c7ae06f6e..e4cf7aff1 100644 --- a/src/client/pv-subscribe.c +++ b/src/client/pv-subscribe.c @@ -70,6 +70,12 @@ notify_subscription (PvSubscribe *subscribe, g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event, PV_SUBSCRIPTION_FLAGS_CLIENT, object); } + 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_SOURCE) { if ((interface == NULL && pv_object_peek_source1 (PV_OBJECT (object))) || PV_IS_SOURCE1_PROXY (interface)) @@ -172,11 +178,18 @@ on_client_manager_ready (GObject *source_object, PvSubscribe *subscribe = user_data; PvSubscribePrivate *priv = subscribe->priv; GError *error = NULL; + GList *objects, *walk; priv->client_manager = pv_object_manager_client_new_finish (res, &error); if (priv->client_manager == NULL) goto manager_error; + 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); return; diff --git a/src/client/pv-subscribe.h b/src/client/pv-subscribe.h index c74025c0c..d1a5278ec 100644 --- a/src/client/pv-subscribe.h +++ b/src/client/pv-subscribe.h @@ -38,12 +38,13 @@ typedef struct _PvSubscribeClass PvSubscribeClass; typedef struct _PvSubscribePrivate PvSubscribePrivate; typedef enum { - PV_SUBSCRIPTION_FLAGS_CLIENT = (1 << 0), - PV_SUBSCRIPTION_FLAGS_SOURCE = (1 << 1), - PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT = (1 << 2), + PV_SUBSCRIPTION_FLAGS_CLIENT = (1 << 0), + PV_SUBSCRIPTION_FLAGS_SOURCE_PROVIDER = (1 << 1), + PV_SUBSCRIPTION_FLAGS_SOURCE = (1 << 2), + PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT = (1 << 3), } PvSubscriptionFlags; -#define PV_SUBSCRIPTION_FLAGS_ALL 0x3 +#define PV_SUBSCRIPTION_FLAGS_ALL 0xf typedef enum { PV_SUBSCRIPTION_EVENT_NEW = 0, diff --git a/src/daemon/main.c b/src/daemon/main.c index 3b6e79b18..cb0fbbfed 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -22,18 +22,23 @@ #include #include +#include gint main (gint argc, gchar *argv[]) { PvDaemon *daemon; GMainLoop *loop; + PvSource *source; pv_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); daemon = pv_daemon_new (); + + source = pv_v4l2_source_new(); + 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 bd17635c5..2fd478f51 100644 --- a/src/dbus/org.pulsevideo.xml +++ b/src/dbus/org.pulsevideo.xml @@ -9,9 +9,6 @@ - - - @@ -29,6 +26,8 @@ + + diff --git a/src/server/pv-client.c b/src/server/pv-client.c index 437665ed5..28c582433 100644 --- a/src/server/pv-client.c +++ b/src/server/pv-client.c @@ -180,20 +180,20 @@ client_register_object (PvClient *client, const gchar *prefix) { PvClientPrivate *priv = client->priv; PvDaemon *daemon = priv->daemon; - GDBusObjectSkeleton *skel; + PvObjectSkeleton *skel; gchar *name; name = g_strdup_printf ("%s/client", prefix); - skel = g_dbus_object_skeleton_new (name); + skel = pv_object_skeleton_new (name); 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); - g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (priv->client1)); + pv_object_skeleton_set_client1 (skel, priv->client1); g_free (priv->object_path); - priv->object_path = pv_daemon_export_uniquely (daemon, skel); + priv->object_path = pv_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel)); } static void diff --git a/src/server/pv-daemon.c b/src/server/pv-daemon.c index 946059d31..3afefaef6 100644 --- a/src/server/pv-daemon.c +++ b/src/server/pv-daemon.c @@ -35,6 +35,7 @@ struct _PvDaemonPrivate guint id; GDBusConnection *connection; GDBusObjectManagerServer *server_manager; + PvSubscribe *subscribe; GHashTable *senders; GList *sources; @@ -52,33 +53,32 @@ typedef struct { } SenderData; static void -on_subscription_event (PvSubscribe *subscribe, - PvSubscriptionEvent event, - PvSubscriptionFlags flags, - GDBusObjectProxy *object, - gpointer user_data) +on_server_subscription_event (PvSubscribe *subscribe, + PvSubscriptionEvent event, + PvSubscriptionFlags flags, + GDBusObjectProxy *object, + gpointer user_data) { - SenderData *data = user_data; - PvDaemon *daemon = data->daemon; + PvDaemon *daemon = user_data; 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); + 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", data->sender); - - g_hash_table_insert (data->sources, g_strdup (object_path), source1); + g_object_set_data (G_OBJECT (source1), "org.pulsevideo.name", service); priv->sources = g_list_prepend (priv->sources, source1); break; } @@ -89,12 +89,49 @@ on_subscription_event (PvSubscribe *subscribe, 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; + + on_server_subscription_event (subscribe, event, flags, object, daemon); + + object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object)); + + 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); + break; + } + + case PV_SUBSCRIPTION_EVENT_CHANGE: + break; + + case PV_SUBSCRIPTION_EVENT_REMOVE: + { g_hash_table_remove (data->sources, object_path); break; } } } + static void client_name_appeared_handler (GDBusConnection *connection, const gchar *name, @@ -113,7 +150,7 @@ client_name_appeared_handler (GDBusConnection *connection, g_signal_connect (data->subscribe, "subscription-event", - (GCallback) on_subscription_event, + (GCallback) on_sender_subscription_event, data); } @@ -192,50 +229,25 @@ handle_connect_client (PvDaemon1 *interface, return TRUE; } -static gboolean -handle_disconnect_client (PvDaemon1 *interface, - GDBusMethodInvocation *invocation, - const gchar *arg_client, - gpointer user_data) -{ - PvDaemon *daemon = user_data; - PvDaemonPrivate *priv = daemon->priv; - const gchar *sender; - SenderData *data; - - sender = g_dbus_method_invocation_get_sender (invocation); - - g_print ("disconnect client %s\n", sender); - data = g_hash_table_lookup (priv->senders, sender); - if (data != NULL) { - g_hash_table_remove (data->clients, arg_client); - } - - pv_daemon1_complete_disconnect_client (interface, invocation); - - return TRUE; -} - static void export_server_object (PvDaemon *daemon, GDBusObjectManagerServer *manager) { - GDBusObjectSkeleton *skel; + PvObjectSkeleton *skel; - skel = g_dbus_object_skeleton_new (PV_DBUS_OBJECT_SERVER); + skel = pv_object_skeleton_new (PV_DBUS_OBJECT_SERVER); { PvDaemon1 *iface; iface = pv_daemon1_skeleton_new (); g_signal_connect (iface, "handle-connect-client", (GCallback) handle_connect_client, daemon); - g_signal_connect (iface, "handle-disconnect-client", (GCallback) handle_disconnect_client, daemon); pv_daemon1_set_user_name (iface, g_get_user_name ()); pv_daemon1_set_host_name (iface, g_get_host_name ()); pv_daemon1_set_version (iface, PACKAGE_VERSION); pv_daemon1_set_name (iface, PACKAGE_NAME); - g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface)); + pv_object_skeleton_set_daemon1 (skel, iface); g_object_unref (iface); } - g_dbus_object_manager_server_export (manager, skel); + g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (skel)); g_object_unref (skel); } @@ -257,10 +269,16 @@ name_acquired_handler (GDBusConnection *connection, { PvDaemon *daemon = user_data; PvDaemonPrivate *priv = daemon->priv; - GDBusObjectManagerServer *manager; + GDBusObjectManagerServer *manager = priv->server_manager; + + g_object_set (priv->subscribe, "service", PV_DBUS_SERVICE, + "subscription-mask", PV_SUBSCRIPTION_FLAGS_SOURCE, + "connection", connection, + NULL); + - priv->server_manager = manager = g_dbus_object_manager_server_new (PV_DBUS_OBJECT_PREFIX); export_server_object (daemon, manager); + g_dbus_object_manager_server_set_connection (manager, connection); } @@ -273,8 +291,10 @@ name_lost_handler (GDBusConnection *connection, PvDaemonPrivate *priv = daemon->priv; GDBusObjectManagerServer *manager = priv->server_manager; + g_object_set (priv->subscribe, "connection", connection, NULL); + g_dbus_object_manager_server_unexport (manager, PV_DBUS_OBJECT_SERVER); - g_clear_object (&priv->server_manager); + g_dbus_object_manager_server_set_connection (manager, connection); } PvDaemon * @@ -334,6 +354,27 @@ pv_daemon_unexport (PvDaemon *daemon, const gchar *object_path) g_dbus_object_manager_server_unexport (daemon->priv->server_manager, object_path); } +void +pv_daemon_add_source (PvDaemon *daemon, PvSource *source) +{ + PvDaemonPrivate *priv; + + g_return_if_fail (PV_IS_DAEMON (daemon)); + g_return_if_fail (PV_IS_SOURCE (source)); + priv = daemon->priv; + + pv_source_set_manager (source, priv->server_manager); +} + +void +pv_daemon_remove_source (PvDaemon *daemon, PvSource *source) +{ + g_return_if_fail (PV_IS_DAEMON (daemon)); + g_return_if_fail (PV_IS_SOURCE (source)); + + pv_source_set_manager (source, NULL); +} + PvSource1 * pv_daemon_get_source (PvDaemon *daemon, const gchar *name) { @@ -359,6 +400,7 @@ pv_daemon_finalize (GObject * object) PvDaemon *daemon = PV_DAEMON_CAST (object); PvDaemonPrivate *priv = daemon->priv; + g_clear_object (&priv->server_manager); g_hash_table_unref (priv->senders); pv_daemon_stop (daemon); @@ -381,5 +423,12 @@ 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->subscribe = pv_subscribe_new (); + g_signal_connect (priv->subscribe, + "subscription-event", + (GCallback) on_server_subscription_event, + daemon); } diff --git a/src/server/pv-daemon.h b/src/server/pv-daemon.h index 4eddcb28b..bdb9c9471 100644 --- a/src/server/pv-daemon.h +++ b/src/server/pv-daemon.h @@ -74,6 +74,9 @@ void pv_daemon_stop (PvDaemon *daemon); gchar * pv_daemon_export_uniquely (PvDaemon *daemon, GDBusObjectSkeleton *skel); void pv_daemon_unexport (PvDaemon *daemon, const gchar *name); +void pv_daemon_add_source (PvDaemon *daemon, PvSource *source); +void pv_daemon_remove_source (PvDaemon *daemon, PvSource *source); + 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 index 0c3fbc0ae..2350c8e7a 100644 --- a/src/server/pv-source-provider.c +++ b/src/server/pv-source-provider.c @@ -113,11 +113,11 @@ source_provider_register_object (PvSourceProvider *client, const gchar *prefix) { PvSourceProviderPrivate *priv = client->priv; PvDaemon *daemon = priv->daemon; - GDBusObjectSkeleton *skel; + PvObjectSkeleton *skel; gchar *name; name = g_strdup_printf ("%s/source", prefix); - skel = g_dbus_object_skeleton_new (name); + skel = pv_object_skeleton_new (name); g_free (name); { @@ -126,12 +126,12 @@ source_provider_register_object (PvSourceProvider *client, const gchar *prefix) 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)); + pv_object_skeleton_set_source_provider1 (skel, iface); g_object_unref (iface); } g_free (priv->object_path); - priv->object_path = pv_daemon_export_uniquely (daemon, skel); + priv->object_path = pv_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel)); } static void