mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-13 13:30:05 -05:00
rework subscription
Rework subscription so that we can use it for client and server. Move source and source-output to client to allow client provided sources. Still needs some work but registration seems to work partly. Rework DBUS API: move CreateSourceOutput to Client1 interface, remove Add/RemoveProvider and Device1 interface. Rework SourceOutput1 to allow for reconfigure. Add a client to test v4l2 source.
This commit is contained in:
parent
75d5fa91e2
commit
752494621c
19 changed files with 775 additions and 388 deletions
|
|
@ -20,10 +20,18 @@
|
|||
#ifndef __PULSEVIDEO_H__
|
||||
#define __PULSEVIDEO_H__
|
||||
|
||||
#include <client/pv-context.h>
|
||||
#include <client/pv-source.h>
|
||||
#include <client/pv-source-output.h>
|
||||
#include <client/pv-stream.h>
|
||||
#include <client/pv-context.h>
|
||||
#include <client/pv-subscribe.h>
|
||||
|
||||
#define PV_DBUS_SERVICE "org.pulsevideo"
|
||||
#define PV_DBUS_OBJECT_PREFIX "/org/pulsevideo"
|
||||
#define PV_DBUS_OBJECT_SERVER PV_DBUS_OBJECT_PREFIX "/server"
|
||||
#define PV_DBUS_OBJECT_SOURCE PV_DBUS_OBJECT_PREFIX "/source"
|
||||
#define PV_DBUS_OBJECT_CLIENT PV_DBUS_OBJECT_PREFIX "/client"
|
||||
|
||||
void pv_init (int *argc, char **argv[]);
|
||||
|
||||
#endif /* __PULSEVIDEO_H__ */
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "server/pv-daemon.h"
|
||||
#include "client/pulsevideo.h"
|
||||
|
||||
#include "client/pv-context.h"
|
||||
#include "client/pv-enumtypes.h"
|
||||
|
|
@ -41,8 +41,9 @@ struct _PvContextPrivate
|
|||
gchar *client_path;
|
||||
PvClient1 *client;
|
||||
|
||||
PvSubscriptionFlags subscription_mask;
|
||||
GDBusObjectManager *client_manager;
|
||||
PvSubscribe *subscribe;
|
||||
|
||||
GDBusObjectManagerServer *server_manager;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -57,21 +58,10 @@ enum
|
|||
PROP_NAME,
|
||||
PROP_PROPERTIES,
|
||||
PROP_STATE,
|
||||
PROP_SUBSCRIPTION_MASK,
|
||||
PROP_CONNECTION,
|
||||
PROP_CLIENT_PATH
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_SUBSCRIPTION_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
#include "pv-subscribe.c"
|
||||
|
||||
static void
|
||||
pv_context_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
|
|
@ -94,10 +84,6 @@ pv_context_get_property (GObject *_object,
|
|||
g_value_set_enum (value, priv->state);
|
||||
break;
|
||||
|
||||
case PROP_SUBSCRIPTION_MASK:
|
||||
g_value_set_flags (value, priv->subscription_mask);
|
||||
break;
|
||||
|
||||
case PROP_CONNECTION:
|
||||
g_value_set_object (value, priv->connection);
|
||||
break;
|
||||
|
|
@ -133,16 +119,24 @@ pv_context_set_property (GObject *_object,
|
|||
priv->properties = g_value_dup_variant (value);
|
||||
break;
|
||||
|
||||
case PROP_SUBSCRIPTION_MASK:
|
||||
priv->subscription_mask = g_value_get_flags (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (context, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_context_finalize (GObject * object)
|
||||
{
|
||||
PvContext *context = PV_CONTEXT (object);
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
g_object_unref (priv->server_manager);
|
||||
|
||||
G_OBJECT_CLASS (pv_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pv_context_class_init (PvContextClass * klass)
|
||||
{
|
||||
|
|
@ -150,6 +144,7 @@ pv_context_class_init (PvContextClass * klass)
|
|||
|
||||
g_type_class_add_private (klass, sizeof (PvContextPrivate));
|
||||
|
||||
gobject_class->finalize = pv_context_finalize;
|
||||
gobject_class->set_property = pv_context_set_property;
|
||||
gobject_class->get_property = pv_context_get_property;
|
||||
|
||||
|
|
@ -194,21 +189,6 @@ pv_context_class_init (PvContextClass * klass)
|
|||
PV_CONTEXT_STATE_UNCONNECTED,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:subscription-mask
|
||||
*
|
||||
* A mask for what object notifications will be signaled with
|
||||
* PvContext:subscription-event
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SUBSCRIPTION_MASK,
|
||||
g_param_spec_flags ("subscription-mask",
|
||||
"Subscription Mask",
|
||||
"The object to receive subscription events of",
|
||||
PV_TYPE_SUBSCRIPTION_FLAGS,
|
||||
0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:connection
|
||||
*
|
||||
|
|
@ -235,27 +215,6 @@ pv_context_class_init (PvContextClass * klass)
|
|||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:subscription-event
|
||||
* @context: The #PvContext emitting the signal.
|
||||
* @event: A #PvSubscriptionEvent
|
||||
* @flags: #PvSubscriptionFlags indicating the object
|
||||
* @path: the object path
|
||||
*
|
||||
* Notify about a new object that was added/removed/modified.
|
||||
*/
|
||||
signals[SIGNAL_SUBSCRIPTION_EVENT] = g_signal_new ("subscription-event",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_generic,
|
||||
G_TYPE_NONE,
|
||||
3,
|
||||
PV_TYPE_SUBSCRIPTION_EVENT,
|
||||
PV_TYPE_SUBSCRIPTION_FLAGS,
|
||||
G_TYPE_STRING);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -264,6 +223,7 @@ pv_context_init (PvContext * context)
|
|||
PvContextPrivate *priv = context->priv = PV_CONTEXT_GET_PRIVATE (context);
|
||||
|
||||
priv->state = PV_CONTEXT_STATE_UNCONNECTED;
|
||||
priv->server_manager = g_dbus_object_manager_server_new (PV_DBUS_OBJECT_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -398,8 +358,12 @@ on_name_appeared (GDBusConnection *connection,
|
|||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
priv->connection = connection;
|
||||
g_dbus_object_manager_server_set_connection (priv->server_manager, connection);
|
||||
|
||||
install_subscription (context);
|
||||
if (priv->subscribe) {
|
||||
g_object_set (priv->subscribe, "connection", priv->connection, NULL);
|
||||
g_object_set (priv->subscribe, "service", name, NULL);
|
||||
}
|
||||
|
||||
pv_daemon1_proxy_new (priv->connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
|
|
@ -418,9 +382,11 @@ on_name_vanished (GDBusConnection *connection,
|
|||
PvContext *context = user_data;
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
uninstall_subscription (context);
|
||||
|
||||
priv->connection = connection;
|
||||
g_dbus_object_manager_server_set_connection (priv->server_manager, connection);
|
||||
|
||||
if (priv->subscribe)
|
||||
g_object_set (priv->subscribe, "connection", connection, NULL);
|
||||
|
||||
if (priv->flags & PV_CONTEXT_FLAGS_NOFAIL) {
|
||||
context_set_state (context, PV_CONTEXT_STATE_CONNECTING);
|
||||
|
|
@ -429,6 +395,28 @@ on_name_vanished (GDBusConnection *connection,
|
|||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_context_set_subscribe (PvContext *context, PvSubscribe *subscribe)
|
||||
{
|
||||
PvContextPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), FALSE);
|
||||
|
||||
priv = context->priv;
|
||||
|
||||
if (priv->subscribe)
|
||||
g_object_unref (priv->subscribe);
|
||||
priv->subscribe = subscribe;
|
||||
|
||||
if (priv->subscribe && priv->connection) {
|
||||
g_object_set (priv->subscribe, "connection", priv->connection,
|
||||
"service", PV_DBUS_SERVICE, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pv_context_connect:
|
||||
* @context: a #PvContext
|
||||
|
|
@ -467,6 +455,32 @@ pv_context_connect (PvContext *context, PvContextFlags flags)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_context_register_source (PvContext *context, PvSource *source)
|
||||
{
|
||||
PvContextPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), FALSE);
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
|
||||
|
||||
priv = context->priv;
|
||||
|
||||
pv_source_set_manager (source, priv->server_manager);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_context_unregister_source (PvContext *context, PvSource *source)
|
||||
{
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), FALSE);
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
|
||||
|
||||
pv_source_set_manager (source, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_context_get_connection:
|
||||
* @context: a #PvContext
|
||||
|
|
@ -483,6 +497,23 @@ pv_context_get_connection (PvContext *context)
|
|||
return context->priv->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_context_get_client_proxy:
|
||||
* @context: a #PvContext
|
||||
*
|
||||
* Get the client proxy that @context is registered with
|
||||
*
|
||||
* Returns: the client proxy of @context or %NULL when not
|
||||
* registered.
|
||||
*/
|
||||
GDBusProxy *
|
||||
pv_context_get_client_proxy (PvContext *context)
|
||||
{
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), NULL);
|
||||
|
||||
return G_DBUS_PROXY (context->priv->client);
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_context_get_client_path:
|
||||
* @context: a #PvContext
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <client/pv-source.h>
|
||||
#include <client/pv-subscribe.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_CONTEXT (pv_context_get_type ())
|
||||
|
|
@ -97,9 +100,15 @@ GType pv_context_get_type (void);
|
|||
|
||||
PvContext * pv_context_new (const gchar *name, GVariant *properties);
|
||||
|
||||
gboolean pv_context_set_subscribe (PvContext *context, PvSubscribe *subscribe);
|
||||
|
||||
gboolean pv_context_connect (PvContext *context, PvContextFlags flags);
|
||||
|
||||
gboolean pv_context_register_source (PvContext *context, PvSource *source);
|
||||
gboolean pv_context_unregister_source (PvContext *context, PvSource *source);
|
||||
|
||||
GDBusConnection * pv_context_get_connection (PvContext *context);
|
||||
GDBusProxy * pv_context_get_client_proxy (PvContext *context);
|
||||
const gchar * pv_context_get_client_path (PvContext *context);
|
||||
|
||||
PvContextState pv_context_get_state (PvContext *context);
|
||||
|
|
|
|||
291
src/client/pv-source-output.c
Normal file
291
src/client/pv-source-output.c
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* 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 <sys/socket.h>
|
||||
|
||||
#include <gio/gunixfdlist.h>
|
||||
|
||||
#include "client/pv-source-output.h"
|
||||
#include "client/pv-enumtypes.h"
|
||||
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
struct _PvSourceOutputPrivate
|
||||
{
|
||||
GDBusObjectManagerServer *server_manager;
|
||||
|
||||
gchar *object_path;
|
||||
|
||||
GSocket *socket;
|
||||
};
|
||||
|
||||
#define PV_SOURCE_OUTPUT_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_SOURCE_OUTPUT, PvSourceOutputPrivate))
|
||||
|
||||
G_DEFINE_TYPE (PvSourceOutput, pv_source_output, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_MANAGER,
|
||||
PROP_OBJECT_PATH,
|
||||
PROP_SOCKET,
|
||||
};
|
||||
|
||||
static void
|
||||
pv_source_output_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (_object);
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MANAGER:
|
||||
g_value_set_object (value, priv->server_manager);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
g_value_set_string (value, priv->object_path);
|
||||
break;
|
||||
|
||||
case PROP_SOCKET:
|
||||
g_value_set_object (value, priv->socket);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (output, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_output_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (_object);
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MANAGER:
|
||||
priv->server_manager = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
priv->object_path = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (output, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_start (PvSourceOutput1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GVariant *arg_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvSourceOutput *output = user_data;
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
GUnixFDList *fdlist;
|
||||
GVariantBuilder props;
|
||||
gint fd[2];
|
||||
|
||||
socketpair (AF_UNIX, SOCK_STREAM, 0, fd);
|
||||
priv->socket = g_socket_new_from_fd (fd[0], NULL);
|
||||
g_object_notify (G_OBJECT (output), "socket");
|
||||
|
||||
g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&props, "{sv}", "name", g_variant_new_string ("hello"));
|
||||
|
||||
fdlist = g_unix_fd_list_new ();
|
||||
g_unix_fd_list_append (fdlist, fd[1], NULL);
|
||||
|
||||
g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,
|
||||
g_variant_new ("(h@a{sv})",
|
||||
0,
|
||||
g_variant_builder_end (&props)),
|
||||
fdlist);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
stop_transfer (PvSourceOutput *output)
|
||||
{
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
if (priv->socket) {
|
||||
g_clear_object (&priv->socket);
|
||||
g_object_notify (G_OBJECT (output), "socket");
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_stop (PvSourceOutput1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvSourceOutput *output = user_data;
|
||||
|
||||
stop_transfer (output);
|
||||
|
||||
pv_source_output1_complete_stop (interface, invocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_remove (PvSourceOutput1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvSourceOutput *output = user_data;
|
||||
|
||||
stop_transfer (output);
|
||||
|
||||
pv_source_output1_complete_remove (interface, invocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
output_register_object (PvSourceOutput *output, const gchar *prefix)
|
||||
{
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
GDBusObjectSkeleton *skel;
|
||||
gchar *name;
|
||||
|
||||
name = g_strdup_printf ("%s/output", prefix);
|
||||
skel = g_dbus_object_skeleton_new (name);
|
||||
g_free (name);
|
||||
|
||||
{
|
||||
PvSourceOutput1 *iface;
|
||||
|
||||
iface = pv_source_output1_skeleton_new ();
|
||||
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));
|
||||
g_object_unref (iface);
|
||||
}
|
||||
g_dbus_object_manager_server_export_uniquely (priv->server_manager, skel);
|
||||
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel)));
|
||||
}
|
||||
|
||||
static void
|
||||
output_unregister_object (PvSourceOutput *output)
|
||||
{
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
stop_transfer (output);
|
||||
|
||||
g_dbus_object_manager_server_unexport (priv->server_manager, priv->object_path);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_output_finalize (GObject * object)
|
||||
{
|
||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (object);
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
output_unregister_object (output);
|
||||
g_object_unref (priv->server_manager);
|
||||
g_free (priv->object_path);
|
||||
|
||||
G_OBJECT_CLASS (pv_source_output_parent_class)->finalize (object);
|
||||
}
|
||||
static void
|
||||
pv_source_output_constructed (GObject * object)
|
||||
{
|
||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (object);
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
output_register_object (output, priv->object_path);
|
||||
|
||||
G_OBJECT_CLASS (pv_source_output_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_output_class_init (PvSourceOutputClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvSourceOutputPrivate));
|
||||
|
||||
gobject_class->finalize = pv_source_output_finalize;
|
||||
gobject_class->set_property = pv_source_output_set_property;
|
||||
gobject_class->get_property = pv_source_output_get_property;
|
||||
gobject_class->constructed = pv_source_output_constructed;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_MANAGER,
|
||||
g_param_spec_object ("manager",
|
||||
"Manager",
|
||||
"The manager",
|
||||
G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
|
||||
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_SOCKET,
|
||||
g_param_spec_object ("socket",
|
||||
"Socket",
|
||||
"The socket with data",
|
||||
G_TYPE_SOCKET,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_output_init (PvSourceOutput * output)
|
||||
{
|
||||
output->priv = PV_SOURCE_OUTPUT_GET_PRIVATE (output);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
pv_source_output_get_object_path (PvSourceOutput *output)
|
||||
{
|
||||
PvSourceOutputPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE_OUTPUT (output), NULL);
|
||||
priv = output->priv;
|
||||
|
||||
return priv->object_path;
|
||||
}
|
||||
|
||||
69
src/client/pv-source-output.h
Normal file
69
src/client/pv-source-output.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* 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_OUTPUT_H__
|
||||
#define __PV_SOURCE_OUTPUT_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_SOURCE_OUTPUT (pv_source_output_get_type ())
|
||||
#define PV_IS_SOURCE_OUTPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_SOURCE_OUTPUT))
|
||||
#define PV_IS_SOURCE_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_SOURCE_OUTPUT))
|
||||
#define PV_SOURCE_OUTPUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_SOURCE_OUTPUT, PvSourceOutputClass))
|
||||
#define PV_SOURCE_OUTPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_SOURCE_OUTPUT, PvSourceOutput))
|
||||
#define PV_SOURCE_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_SOURCE_OUTPUT, PvSourceOutputClass))
|
||||
#define PV_SOURCE_OUTPUT_CAST(obj) ((PvSourceOutput*)(obj))
|
||||
#define PV_SOURCE_OUTPUT_CLASS_CAST(klass) ((PvSourceOutputClass*)(klass))
|
||||
|
||||
typedef struct _PvSourceOutput PvSourceOutput;
|
||||
typedef struct _PvSourceOutputClass PvSourceOutputClass;
|
||||
typedef struct _PvSourceOutputPrivate PvSourceOutputPrivate;
|
||||
|
||||
/**
|
||||
* PvSourceOutput:
|
||||
*
|
||||
* Pulsevideo source output object class.
|
||||
*/
|
||||
struct _PvSourceOutput {
|
||||
GObject object;
|
||||
|
||||
PvSourceOutputPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvSourceOutputClass:
|
||||
*
|
||||
* Pulsevideo source output object class.
|
||||
*/
|
||||
struct _PvSourceOutputClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_source_output_get_type (void);
|
||||
|
||||
const gchar * pv_source_output_get_sender (PvSourceOutput *output);
|
||||
const gchar * pv_source_output_get_object_path (PvSourceOutput *output);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_SOURCE_OUTPUT_H__ */
|
||||
|
||||
305
src/client/pv-source.c
Normal file
305
src/client/pv-source.c
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* 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 <gio/gio.h>
|
||||
|
||||
#include "client/pulsevideo.h"
|
||||
#include "client/pv-source.h"
|
||||
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
|
||||
#define PV_SOURCE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_SOURCE, PvSourcePrivate))
|
||||
|
||||
struct _PvSourcePrivate
|
||||
{
|
||||
GDBusObjectManagerServer *server_manager;
|
||||
|
||||
gchar *object_path;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (PvSource, pv_source, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_MANAGER,
|
||||
PROP_OBJECT_PATH
|
||||
};
|
||||
|
||||
static void
|
||||
pv_source_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSource *source = PV_SOURCE (_object);
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MANAGER:
|
||||
g_value_set_object (value, priv->server_manager);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
g_value_set_string (value, priv->object_path);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (source, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSource *source = PV_SOURCE (_object);
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MANAGER:
|
||||
pv_source_set_manager (source, g_value_dup_object (value));
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (source, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
source_register_object (PvSource *source)
|
||||
{
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
GDBusObjectSkeleton *skel;
|
||||
|
||||
skel = g_dbus_object_skeleton_new (PV_DBUS_OBJECT_SOURCE);
|
||||
{
|
||||
PvSource1 *iface;
|
||||
|
||||
iface = pv_source1_skeleton_new ();
|
||||
g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
|
||||
g_object_unref (iface);
|
||||
}
|
||||
g_dbus_object_manager_server_export_uniquely (priv->server_manager, skel);
|
||||
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
source_unregister_object (PvSource *source)
|
||||
{
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
g_dbus_object_manager_server_unexport (priv->server_manager, priv->object_path);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_finalize (GObject * object)
|
||||
{
|
||||
PvSource *source = PV_SOURCE (object);
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
if (priv->server_manager) {
|
||||
source_unregister_object (source);
|
||||
g_object_unref (priv->server_manager);
|
||||
}
|
||||
g_free (priv->object_path);
|
||||
|
||||
G_OBJECT_CLASS (pv_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static PvSourceOutput *
|
||||
default_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
|
||||
{
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
return g_object_new (PV_TYPE_SOURCE_OUTPUT, "manager", priv->server_manager, "object-path", prefix, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
default_release_source_output (PvSource *source, PvSourceOutput *output)
|
||||
{
|
||||
g_object_unref (output);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pv_source_class_init (PvSourceClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvSourcePrivate));
|
||||
|
||||
gobject_class->finalize = pv_source_finalize;
|
||||
gobject_class->set_property = pv_source_set_property;
|
||||
gobject_class->get_property = pv_source_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_MANAGER,
|
||||
g_param_spec_object ("manager",
|
||||
"Manager",
|
||||
"The manager",
|
||||
G_TYPE_DBUS_OBJECT_MANAGER_SERVER,
|
||||
G_PARAM_READWRITE |
|
||||
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_STATIC_STRINGS));
|
||||
|
||||
klass->create_source_output = default_create_source_output;
|
||||
klass->release_source_output = default_release_source_output;
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_init (PvSource * source)
|
||||
{
|
||||
source->priv = PV_SOURCE_GET_PRIVATE (source);
|
||||
}
|
||||
|
||||
void
|
||||
pv_source_set_manager (PvSource *source, GDBusObjectManagerServer *manager)
|
||||
{
|
||||
PvSourcePrivate *priv;
|
||||
|
||||
g_return_if_fail (PV_IS_SOURCE (source));
|
||||
priv = source->priv;
|
||||
|
||||
if (priv->server_manager) {
|
||||
source_unregister_object (source);
|
||||
g_object_unref (priv->server_manager);
|
||||
}
|
||||
priv->server_manager = manager;
|
||||
|
||||
if (priv->server_manager) {
|
||||
source_register_object (source);
|
||||
}
|
||||
}
|
||||
|
||||
GVariant *
|
||||
pv_source_get_capabilities (PvSource *source, GVariant *props)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
GVariant *res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), NULL);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->get_capabilities)
|
||||
res = klass->get_capabilities (source, props);
|
||||
else
|
||||
res = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_source_suspend (PvSource *source)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->suspend)
|
||||
res = klass->suspend (source);
|
||||
else
|
||||
res = FALSE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_source_resume (PvSource *source)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->resume)
|
||||
res = klass->resume (source);
|
||||
else
|
||||
res = FALSE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
PvSourceOutput *
|
||||
pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
PvSourceOutput *res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), NULL);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->create_source_output)
|
||||
res = klass->create_source_output (source, props, prefix);
|
||||
else
|
||||
res = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_source_release_source_output (PvSource *source, PvSourceOutput *output)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
|
||||
g_return_val_if_fail (PV_IS_SOURCE_OUTPUT (output), FALSE);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->release_source_output)
|
||||
res = klass->release_source_output (source, output);
|
||||
else
|
||||
res = FALSE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
87
src/client/pv-source.h
Normal file
87
src/client/pv-source.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* 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_H__
|
||||
#define __PV_SOURCE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _PvSource PvSource;
|
||||
typedef struct _PvSourceClass PvSourceClass;
|
||||
typedef struct _PvSourcePrivate PvSourcePrivate;
|
||||
|
||||
#include "client/pv-source-output.h"
|
||||
|
||||
#define PV_TYPE_SOURCE (pv_source_get_type ())
|
||||
#define PV_IS_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_SOURCE))
|
||||
#define PV_IS_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_SOURCE))
|
||||
#define PV_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_SOURCE, PvSourceClass))
|
||||
#define PV_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_SOURCE, PvSource))
|
||||
#define PV_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_SOURCE, PvSourceClass))
|
||||
#define PV_SOURCE_CAST(obj) ((PvSource*)(obj))
|
||||
#define PV_SOURCE_CLASS_CAST(klass) ((PvSourceClass*)(klass))
|
||||
|
||||
/**
|
||||
* PvSource:
|
||||
*
|
||||
* Pulsevideo source object class.
|
||||
*/
|
||||
struct _PvSource {
|
||||
GObject object;
|
||||
|
||||
PvSourcePrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvSourceClass:
|
||||
*
|
||||
* Pulsevideo source object class.
|
||||
*/
|
||||
struct _PvSourceClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
GVariant * (*get_capabilities) (PvSource *source, GVariant *props);
|
||||
|
||||
gboolean (*suspend) (PvSource *source);
|
||||
gboolean (*resume) (PvSource *source);
|
||||
|
||||
PvSourceOutput * (*create_source_output) (PvSource *source, GVariant *props, const gchar *prefix);
|
||||
gboolean (*release_source_output) (PvSource *source, PvSourceOutput *output);
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_source_get_type (void);
|
||||
|
||||
void pv_source_set_manager (PvSource *source, GDBusObjectManagerServer *manager);
|
||||
|
||||
GVariant * pv_source_get_capabilities (PvSource *source, GVariant *props);
|
||||
|
||||
gboolean pv_source_suspend (PvSource *source);
|
||||
gboolean pv_source_resume (PvSource *source);
|
||||
|
||||
PvSourceOutput * pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *prefix);
|
||||
gboolean pv_source_release_source_output (PvSource *source, PvSourceOutput *output);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_SOURCE_H__ */
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ struct _PvStreamPrivate
|
|||
gchar *target;
|
||||
PvStreamState state;
|
||||
|
||||
PvCapture1 *capture;
|
||||
gchar *source_output_sender;
|
||||
gchar *source_output_path;
|
||||
PvSourceOutput1 *source_output;
|
||||
|
||||
|
|
@ -275,6 +275,14 @@ pv_stream_get_state (PvStream *stream)
|
|||
return stream->priv->state;
|
||||
}
|
||||
|
||||
static void
|
||||
on_request_reconfigure (PvSourceOutput1 *interface,
|
||||
GVariant *props,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("on request reconfigure\n");
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_output1_proxy (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
|
|
@ -285,13 +293,21 @@ on_source_output1_proxy (GObject *source_object,
|
|||
GError *error = NULL;
|
||||
|
||||
priv->source_output = pv_source_output1_proxy_new_finish (res, &error);
|
||||
if (priv->source_output == NULL) {
|
||||
if (priv->source_output == NULL)
|
||||
goto source_output_failed;
|
||||
|
||||
g_signal_connect (priv->source_output, "request-reconfigure", (GCallback) on_request_reconfigure, stream);
|
||||
stream_set_state (stream, PV_STREAM_STATE_READY);
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
source_output_failed:
|
||||
{
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to get source output proxy: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
stream_set_state (stream, PV_STREAM_STATE_READY);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -303,22 +319,31 @@ on_source_output_created (GObject *source_object,
|
|||
PvStreamPrivate *priv = stream->priv;
|
||||
PvContext *context = priv->context;
|
||||
GError *error = NULL;
|
||||
PvClient1 *proxy;
|
||||
|
||||
if (!pv_capture1_call_create_source_output_finish (priv->capture,
|
||||
&priv->source_output_path, res, &error)) {
|
||||
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))
|
||||
goto create_failed;
|
||||
|
||||
pv_source_output1_proxy_new (pv_context_get_connection (context),
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
priv->source_output_sender,
|
||||
priv->source_output_path,
|
||||
NULL,
|
||||
on_source_output1_proxy,
|
||||
stream);
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
create_failed:
|
||||
{
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_print ("failed to get connect capture: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
pv_source_output1_proxy_new (pv_context_get_connection (context),
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
PV_DBUS_SERVICE,
|
||||
priv->source_output_path,
|
||||
NULL,
|
||||
on_source_output1_proxy,
|
||||
stream);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -326,16 +351,19 @@ 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"));
|
||||
|
||||
pv_capture1_call_create_source_output (priv->capture,
|
||||
priv->target ? priv->target : "/", /* const gchar *arg_source */
|
||||
g_variant_builder_end (&builder), /* GVariant *arg_props */
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_source_output_created,
|
||||
stream);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -348,13 +376,14 @@ on_source_output_removed (GObject *source_object,
|
|||
PvStreamPrivate *priv = stream->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!pv_capture1_call_remove_source_output_finish (priv->capture,
|
||||
if (!pv_source_output1_call_remove_finish (priv->source_output,
|
||||
res, &error)) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_print ("failed to disconnect: %s", error->message);
|
||||
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);
|
||||
}
|
||||
|
|
@ -364,35 +393,13 @@ remove_source_output (PvStream *stream)
|
|||
{
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
|
||||
pv_capture1_call_remove_source_output (priv->capture,
|
||||
priv->source_output_path,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_source_output_removed,
|
||||
stream);
|
||||
pv_source_output1_call_remove (priv->source_output,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_source_output_removed,
|
||||
stream);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_capture_proxy (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->capture = pv_capture1_proxy_new_finish (res, &error);
|
||||
if (priv->capture == NULL) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to get capture proxy: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
create_source_output (stream);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pv_stream_connect_capture:
|
||||
* @stream: a #PvStream
|
||||
|
|
@ -420,19 +427,7 @@ pv_stream_connect_capture (PvStream *stream,
|
|||
|
||||
stream_set_state (stream, PV_STREAM_STATE_CONNECTING);
|
||||
|
||||
if (priv->capture == NULL) {
|
||||
pv_capture1_proxy_new (pv_context_get_connection (context),
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
PV_DBUS_SERVICE,
|
||||
pv_context_get_client_path (context),
|
||||
NULL,
|
||||
on_capture_proxy,
|
||||
stream);
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
return create_source_output (stream);
|
||||
}
|
||||
return create_source_output (stream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -452,7 +447,7 @@ pv_stream_disconnect (PvStream *stream)
|
|||
g_return_val_if_fail (PV_IS_STREAM (stream), FALSE);
|
||||
priv = stream->priv;
|
||||
g_return_val_if_fail (priv->state >= PV_STREAM_STATE_READY, FALSE);
|
||||
g_return_val_if_fail (priv->capture != NULL, FALSE);
|
||||
g_return_val_if_fail (priv->source_output != NULL, FALSE);
|
||||
context = priv->context;
|
||||
g_return_val_if_fail (pv_context_get_state (context) == PV_CONTEXT_STATE_READY, FALSE);
|
||||
|
||||
|
|
@ -528,12 +523,8 @@ handle_socket (PvStream *stream, gint fd)
|
|||
|
||||
g_print ("got fd %d\n", fd);
|
||||
priv->socket = g_socket_new_from_fd (fd, &error);
|
||||
if (priv->socket == NULL) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to create socket: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
if (priv->socket == NULL)
|
||||
goto socket_failed;
|
||||
|
||||
switch (priv->mode) {
|
||||
case PV_STREAM_MODE_SOCKET:
|
||||
|
|
@ -554,6 +545,16 @@ handle_socket (PvStream *stream, gint fd)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
socket_failed:
|
||||
{
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to create socket: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -573,9 +574,9 @@ unhandle_socket (PvStream *stream)
|
|||
}
|
||||
|
||||
static void
|
||||
on_stream_acquired (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
on_stream_started (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
|
|
@ -585,13 +586,12 @@ on_stream_acquired (GObject *source_object,
|
|||
GError *error = NULL;
|
||||
GVariant *result;
|
||||
|
||||
result = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (priv->source_output), &out_fd_list, res, &error);
|
||||
if (result == NULL) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to acquire: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
result = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (priv->source_output),
|
||||
&out_fd_list,
|
||||
res,
|
||||
&error);
|
||||
if (result == NULL)
|
||||
goto start_failed;
|
||||
|
||||
g_variant_get (result,
|
||||
"(h@a{sv})",
|
||||
|
|
@ -601,16 +601,32 @@ on_stream_acquired (GObject *source_object,
|
|||
g_variant_unref (result);
|
||||
g_variant_unref (out_props);
|
||||
|
||||
if ((fd = g_unix_fd_list_get (out_fd_list, fd_idx, &error)) < 0) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to get FD: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
if ((fd = g_unix_fd_list_get (out_fd_list, fd_idx, &error)) < 0)
|
||||
goto fd_failed;
|
||||
|
||||
handle_socket (stream, fd);
|
||||
|
||||
stream_set_state (stream, PV_STREAM_STATE_STREAMING);
|
||||
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
start_failed:
|
||||
{
|
||||
g_error ("failed to start: %s", error->message);
|
||||
goto exit_error;
|
||||
}
|
||||
fd_failed:
|
||||
{
|
||||
g_error ("failed to get FD: %s", error->message);
|
||||
goto exit_error;
|
||||
}
|
||||
exit_error:
|
||||
{
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -648,34 +664,42 @@ pv_stream_start (PvStream *stream, PvStreamMode mode)
|
|||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string ("hello"));
|
||||
|
||||
pv_source_output1_call_acquire (priv->source_output,
|
||||
g_variant_builder_end (&builder), /* GVariant *arg_properties */
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_stream_acquired,
|
||||
stream);
|
||||
pv_source_output1_call_start (priv->source_output,
|
||||
g_variant_builder_end (&builder), /* GVariant *arg_properties */
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_stream_started,
|
||||
stream);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_stream_released (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
on_stream_stopped (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!pv_source_output1_call_release_finish (priv->source_output,
|
||||
res, &error)) {
|
||||
if (!pv_source_output1_call_stop_finish (priv->source_output,
|
||||
res, &error))
|
||||
goto call_failed;
|
||||
|
||||
unhandle_socket (stream);
|
||||
|
||||
stream_set_state (stream, PV_STREAM_STATE_READY);
|
||||
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
call_failed:
|
||||
{
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to release: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
unhandle_socket (stream);
|
||||
|
||||
stream_set_state (stream, PV_STREAM_STATE_READY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -696,10 +720,10 @@ pv_stream_stop (PvStream *stream)
|
|||
priv = stream->priv;
|
||||
g_return_val_if_fail (priv->state == PV_STREAM_STATE_STREAMING, FALSE);
|
||||
|
||||
pv_source_output1_call_release (priv->source_output,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_stream_released,
|
||||
stream);
|
||||
pv_source_output1_call_stop (priv->source_output,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_stream_stopped,
|
||||
stream);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,36 +17,69 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
static void
|
||||
notify_subscription (PvContext *context,
|
||||
GDBusObject *object,
|
||||
GDBusInterface *interface,
|
||||
PvSubscriptionEvent event)
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "client/pulsevideo.h"
|
||||
#include "client/pv-enumtypes.h"
|
||||
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
struct _PvSubscribePrivate
|
||||
{
|
||||
PvContextPrivate *priv = context->priv;
|
||||
GDBusConnection *connection;
|
||||
gchar *service;
|
||||
|
||||
PvSubscriptionFlags subscription_mask;
|
||||
|
||||
GDBusObjectManager *client_manager;
|
||||
};
|
||||
|
||||
|
||||
#define PV_SUBSCRIBE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_SUBSCRIBE, PvSubscribePrivate))
|
||||
|
||||
G_DEFINE_TYPE (PvSubscribe, pv_subscribe, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CONNECTION,
|
||||
PROP_SERVICE,
|
||||
PROP_SUBSCRIPTION_MASK
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_SUBSCRIPTION_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
notify_subscription (PvSubscribe *subscribe,
|
||||
GDBusObject *object,
|
||||
GDBusInterface *interface,
|
||||
PvSubscriptionEvent event)
|
||||
{
|
||||
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))
|
||||
g_signal_emit (context, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
PV_SUBSCRIPTION_FLAGS_CLIENT, g_dbus_object_get_object_path (object));
|
||||
}
|
||||
if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_DEVICE) {
|
||||
if ((interface == NULL && pv_object_peek_device1 (PV_OBJECT (object))) ||
|
||||
PV_IS_DEVICE1_PROXY (interface))
|
||||
g_signal_emit (context, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
PV_SUBSCRIPTION_FLAGS_DEVICE, g_dbus_object_get_object_path (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 (context, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE, g_dbus_object_get_object_path (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 (context, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT, g_dbus_object_get_object_path (object));
|
||||
}
|
||||
}
|
||||
|
|
@ -57,8 +90,8 @@ on_client_manager_interface_added (GDBusObjectManager *manager,
|
|||
GDBusInterface *interface,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
notify_subscription (context, object, interface, PV_SUBSCRIPTION_EVENT_NEW);
|
||||
PvSubscribe *subscribe = user_data;
|
||||
notify_subscription (subscribe, object, interface, PV_SUBSCRIPTION_EVENT_NEW);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -67,8 +100,8 @@ on_client_manager_interface_removed (GDBusObjectManager *manager,
|
|||
GDBusInterface *interface,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
notify_subscription (context, object, interface, PV_SUBSCRIPTION_EVENT_REMOVE);
|
||||
PvSubscribe *subscribe = user_data;
|
||||
notify_subscription (subscribe, object, interface, PV_SUBSCRIPTION_EVENT_REMOVE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -76,8 +109,8 @@ on_client_manager_object_added (GDBusObjectManager *manager,
|
|||
GDBusObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
notify_subscription (context, object, NULL, PV_SUBSCRIPTION_EVENT_NEW);
|
||||
PvSubscribe *subscribe = user_data;
|
||||
notify_subscription (subscribe, object, NULL, PV_SUBSCRIPTION_EVENT_NEW);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -85,8 +118,8 @@ on_client_manager_object_removed (GDBusObjectManager *manager,
|
|||
GDBusObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
notify_subscription (context, object, NULL, PV_SUBSCRIPTION_EVENT_REMOVE);
|
||||
PvSubscribe *subscribe = user_data;
|
||||
notify_subscription (subscribe, object, NULL, PV_SUBSCRIPTION_EVENT_REMOVE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -113,22 +146,22 @@ on_client_manager_signal (GDBusObjectManagerClient *manager,
|
|||
}
|
||||
|
||||
static void
|
||||
connect_client_signals (PvContext *context)
|
||||
connect_client_signals (PvSubscribe *subscribe)
|
||||
{
|
||||
PvContextPrivate *priv = context->priv;
|
||||
PvSubscribePrivate *priv = subscribe->priv;
|
||||
|
||||
g_signal_connect (priv->client_manager, "interface-added",
|
||||
(GCallback) on_client_manager_interface_added, context);
|
||||
(GCallback) on_client_manager_interface_added, subscribe);
|
||||
g_signal_connect (priv->client_manager, "interface-removed",
|
||||
(GCallback) on_client_manager_interface_removed, context);
|
||||
(GCallback) on_client_manager_interface_removed, subscribe);
|
||||
g_signal_connect (priv->client_manager, "object-added",
|
||||
(GCallback) on_client_manager_object_added, context);
|
||||
(GCallback) on_client_manager_object_added, subscribe);
|
||||
g_signal_connect (priv->client_manager, "object-removed",
|
||||
(GCallback) on_client_manager_object_removed, context);
|
||||
(GCallback) on_client_manager_object_removed, subscribe);
|
||||
g_signal_connect (priv->client_manager, "interface-proxy-signal",
|
||||
(GCallback) on_client_manager_signal, context);
|
||||
(GCallback) on_client_manager_signal, subscribe);
|
||||
g_signal_connect (priv->client_manager, "interface-proxy-properties-changed",
|
||||
(GCallback) on_client_manager_properties_changed, context);
|
||||
(GCallback) on_client_manager_properties_changed, subscribe);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -136,15 +169,15 @@ on_client_manager_ready (GObject *source_object,
|
|||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
PvContextPrivate *priv = context->priv;
|
||||
PvSubscribe *subscribe = user_data;
|
||||
PvSubscribePrivate *priv = subscribe->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->client_manager = pv_object_manager_client_new_finish (res, &error);
|
||||
if (priv->client_manager == NULL)
|
||||
goto manager_error;
|
||||
|
||||
connect_client_signals (context);
|
||||
connect_client_signals (subscribe);
|
||||
|
||||
return;
|
||||
|
||||
|
|
@ -158,26 +191,196 @@ manager_error:
|
|||
}
|
||||
|
||||
static void
|
||||
install_subscription (PvContext *context)
|
||||
install_subscription (PvSubscribe *subscribe)
|
||||
{
|
||||
PvContextPrivate *priv = context->priv;
|
||||
PvSubscribePrivate *priv = subscribe->priv;
|
||||
|
||||
if (priv->client_manager)
|
||||
return;
|
||||
|
||||
pv_object_manager_client_new (pv_context_get_connection (context),
|
||||
pv_object_manager_client_new (priv->connection,
|
||||
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
|
||||
PV_DBUS_SERVICE,
|
||||
priv->service,
|
||||
PV_DBUS_OBJECT_PREFIX,
|
||||
NULL,
|
||||
on_client_manager_ready,
|
||||
context);
|
||||
subscribe);
|
||||
}
|
||||
|
||||
static void
|
||||
uninstall_subscription (PvContext *context)
|
||||
uninstall_subscription (PvSubscribe *subscribe)
|
||||
{
|
||||
PvContextPrivate *priv = context->priv;
|
||||
PvSubscribePrivate *priv = subscribe->priv;
|
||||
|
||||
g_clear_object (&priv->client_manager);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_subscribe_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSubscribe *subscribe = PV_SUBSCRIBE (_object);
|
||||
PvSubscribePrivate *priv = subscribe->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION:
|
||||
g_value_set_object (value, priv->connection);
|
||||
break;
|
||||
|
||||
case PROP_SERVICE:
|
||||
g_value_set_string (value, priv->service);
|
||||
break;
|
||||
|
||||
case PROP_SUBSCRIPTION_MASK:
|
||||
g_value_set_flags (value, priv->subscription_mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (subscribe, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_subscribe_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSubscribe *subscribe = PV_SUBSCRIBE (_object);
|
||||
PvSubscribePrivate *priv = subscribe->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CONNECTION:
|
||||
{
|
||||
uninstall_subscription (subscribe);
|
||||
if (priv->connection)
|
||||
g_object_unref (priv->connection);
|
||||
priv->connection = g_value_dup_object (value);
|
||||
install_subscription (subscribe);
|
||||
break;
|
||||
}
|
||||
|
||||
case PROP_SERVICE:
|
||||
g_free (priv->service);
|
||||
priv->service = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_SUBSCRIPTION_MASK:
|
||||
priv->subscription_mask = g_value_get_flags (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (subscribe, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_subscribe_finalize (GObject * object)
|
||||
{
|
||||
PvSubscribe *subscribe = PV_SUBSCRIBE (object);
|
||||
PvSubscribePrivate *priv = subscribe->priv;
|
||||
|
||||
g_free (priv->service);
|
||||
g_object_unref (priv->client_manager);
|
||||
|
||||
G_OBJECT_CLASS (pv_subscribe_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_subscribe_class_init (PvSubscribeClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvSubscribePrivate));
|
||||
|
||||
gobject_class->finalize = pv_subscribe_finalize;
|
||||
gobject_class->set_property = pv_subscribe_set_property;
|
||||
gobject_class->get_property = pv_subscribe_get_property;
|
||||
|
||||
/**
|
||||
* PvSubscribe:connection
|
||||
*
|
||||
* The connection of the subscribe.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_CONNECTION,
|
||||
g_param_spec_object ("connection",
|
||||
"Connection",
|
||||
"The DBus connection",
|
||||
G_TYPE_DBUS_CONNECTION,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvSubscribe:service
|
||||
*
|
||||
* The service of the subscribe.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SERVICE,
|
||||
g_param_spec_string ("service",
|
||||
"Service",
|
||||
"The service",
|
||||
PV_DBUS_SERVICE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvSubscribe:subscription-mask
|
||||
*
|
||||
* A mask for what object notifications will be signaled with
|
||||
* PvSubscribe:subscription-event
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SUBSCRIPTION_MASK,
|
||||
g_param_spec_flags ("subscription-mask",
|
||||
"Subscription Mask",
|
||||
"The object to receive subscription events of",
|
||||
PV_TYPE_SUBSCRIPTION_FLAGS,
|
||||
0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvSubscribe:subscription-event
|
||||
* @subscribe: The #PvSubscribe emitting the signal.
|
||||
* @event: A #PvSubscriptionEvent
|
||||
* @flags: #PvSubscriptionFlags indicating the object
|
||||
* @path: the object path
|
||||
*
|
||||
* Notify about a new object that was added/removed/modified.
|
||||
*/
|
||||
signals[SIGNAL_SUBSCRIPTION_EVENT] = g_signal_new ("subscription-event",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_generic,
|
||||
G_TYPE_NONE,
|
||||
3,
|
||||
PV_TYPE_SUBSCRIPTION_EVENT,
|
||||
PV_TYPE_SUBSCRIPTION_FLAGS,
|
||||
G_TYPE_STRING);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_subscribe_init (PvSubscribe * subscribe)
|
||||
{
|
||||
PvSubscribePrivate *priv = subscribe->priv = PV_SUBSCRIBE_GET_PRIVATE (subscribe);
|
||||
|
||||
priv->service = g_strdup (PV_DBUS_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_subscribe_new:
|
||||
* @name: an application name
|
||||
* @properties: optional properties
|
||||
*
|
||||
* Make a new unconnected #PvSubscribe
|
||||
*
|
||||
* Returns: a new unconnected #PvSubscribe
|
||||
*/
|
||||
PvSubscribe *
|
||||
pv_subscribe_new (void)
|
||||
{
|
||||
return g_object_new (PV_TYPE_SUBSCRIBE, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,23 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_SUBSCRIBE (pv_subscribe_get_type ())
|
||||
#define PV_IS_SUBSCRIBE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_SUBSCRIBE))
|
||||
#define PV_IS_SUBSCRIBE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_SUBSCRIBE))
|
||||
#define PV_SUBSCRIBE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_SUBSCRIBE, PvSubscribeClass))
|
||||
#define PV_SUBSCRIBE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_SUBSCRIBE, PvSubscribe))
|
||||
#define PV_SUBSCRIBE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_SUBSCRIBE, PvSubscribeClass))
|
||||
#define PV_SUBSCRIBE_CAST(obj) ((PvSubscribe*)(obj))
|
||||
#define PV_SUBSCRIBE_CLASS_CAST(klass) ((PvSubscribeClass*)(klass))
|
||||
|
||||
typedef struct _PvSubscribe PvSubscribe;
|
||||
typedef struct _PvSubscribeClass PvSubscribeClass;
|
||||
typedef struct _PvSubscribePrivate PvSubscribePrivate;
|
||||
|
||||
typedef enum {
|
||||
PV_SUBSCRIPTION_FLAGS_CLIENT = (1 << 0),
|
||||
PV_SUBSCRIPTION_FLAGS_DEVICE = (1 << 1),
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE = (1 << 2),
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT = (1 << 3),
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE = (1 << 1),
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT = (1 << 2),
|
||||
|
||||
PV_SUBSCRIPTION_FLAGS_ALL = 0xf
|
||||
} PvSubscriptionFlags;
|
||||
|
|
@ -39,6 +51,31 @@ typedef enum {
|
|||
PV_SUBSCRIPTION_EVENT_REMOVE = 2,
|
||||
} PvSubscriptionEvent;
|
||||
|
||||
/**
|
||||
* PvSubscribe:
|
||||
*
|
||||
* Pulsevideo subscribe object class.
|
||||
*/
|
||||
struct _PvSubscribe {
|
||||
GObject object;
|
||||
|
||||
PvSubscribePrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvSubscribeClass:
|
||||
*
|
||||
* Pulsevideo subscribe object class.
|
||||
*/
|
||||
struct _PvSubscribeClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_subscribe_get_type (void);
|
||||
|
||||
PvSubscribe * pv_subscribe_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_SUBSCRIBE_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue