handle remote and local sources better

Track remote and local sources separately and make SourceProvider1
interfaces for remote objects so that we get the subscription right.

Move disconnect from the Manager1 to Client1 interface and implement
in the context.
This commit is contained in:
Wim Taymans 2015-04-20 17:24:58 +02:00
parent 93c246c4ce
commit 09de2d3db9
12 changed files with 184 additions and 70 deletions

View file

@ -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)
{

View file

@ -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);

View file

@ -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)));

View file

@ -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)));

View file

@ -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;

View file

@ -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,