mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
remove client object
Remove the client object, it is not very useful now that we have the nodes. Fix some properties on the proxy objects. Use sendmsg and recvmsg directly because the GIO ones do allocations. make pinos_properties_merge and use it to combine properties from nodes and ports.
This commit is contained in:
parent
60475165d6
commit
5f10a933a1
22 changed files with 298 additions and 1030 deletions
|
|
@ -211,7 +211,6 @@ lib_LTLIBRARIES += libpinoscore-@PINOS_MAJORMINOR@.la
|
|||
|
||||
# Pure core stuff
|
||||
libpinoscore_@PINOS_MAJORMINOR@_la_SOURCES = \
|
||||
server/client.c server/client.h \
|
||||
server/daemon.c server/daemon.h \
|
||||
server/server-node.c server/server-node.h \
|
||||
server/server-port.c server/server-port.h \
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ client_node_create_port (PinosNode *node,
|
|||
data->direction = direction;
|
||||
data->name = g_strdup (name);
|
||||
data->possible_formats = possible_formats ? g_bytes_ref (possible_formats) : NULL;
|
||||
data->properties = properties ? pinos_properties_copy (properties) : NULL;
|
||||
data->properties = pinos_properties_merge (pinos_node_get_properties (node), properties);
|
||||
|
||||
g_task_set_task_data (task, data, (GDestroyNotify) create_port_data_free);
|
||||
|
||||
|
|
@ -365,3 +365,43 @@ pinos_client_node_get_context (PinosClientNode *node)
|
|||
|
||||
return priv->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_client_port_new:
|
||||
* @node: a #PinosClientNode
|
||||
* @id: an id
|
||||
* @socket: a socket with the server port
|
||||
*
|
||||
* Create a new client port.
|
||||
*
|
||||
* Returns: a new client port
|
||||
*/
|
||||
PinosClientNode *
|
||||
pinos_client_node_new (PinosContext *context,
|
||||
gpointer id)
|
||||
{
|
||||
PinosClientNode *node;
|
||||
GDBusProxy *proxy = id;
|
||||
GVariant *variant;
|
||||
PinosProperties *properties = NULL;
|
||||
const gchar *name = NULL;
|
||||
|
||||
variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Name");
|
||||
if (variant != NULL) {
|
||||
name = g_variant_get_string (variant, NULL);
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties");
|
||||
if (variant != NULL) {
|
||||
properties = pinos_properties_from_variant (variant);
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
node = g_object_new (PINOS_TYPE_CLIENT_NODE,
|
||||
"context", context,
|
||||
"proxy", proxy,
|
||||
"name", name,
|
||||
"properties", properties,
|
||||
NULL);
|
||||
return node;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ struct _PinosClientNodeClass {
|
|||
/* normal GObject stuff */
|
||||
GType pinos_client_node_get_type (void);
|
||||
|
||||
PinosClientNode * pinos_client_node_new (PinosContext *context,
|
||||
gpointer id);
|
||||
|
||||
PinosContext * pinos_client_node_get_context (PinosClientNode *node);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
|||
|
|
@ -150,7 +150,6 @@ pinos_context_finalize (GObject * object)
|
|||
|
||||
g_list_free (priv->nodes);
|
||||
g_list_free (priv->ports);
|
||||
g_list_free (priv->clients);
|
||||
g_clear_object (&priv->subscribe);
|
||||
g_clear_error (&priv->error);
|
||||
|
||||
|
|
@ -377,62 +376,6 @@ context_set_state (PinosContext *context,
|
|||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
static void
|
||||
on_client_proxy (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosContext *context = user_data;
|
||||
PinosContextPrivate *priv = context->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->client = pinos_subscribe_get_proxy_finish (priv->subscribe,
|
||||
res,
|
||||
&error);
|
||||
if (priv->client == NULL)
|
||||
goto client_failed;
|
||||
|
||||
context_set_state (context, PINOS_CONTEXT_STATE_READY, NULL);
|
||||
|
||||
return;
|
||||
|
||||
client_failed:
|
||||
{
|
||||
g_warning ("failed to get client proxy: %s", error->message);
|
||||
context_set_state (context, PINOS_STREAM_STATE_ERROR, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_connected (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosContext *context = user_data;
|
||||
PinosContextPrivate *priv = context->priv;
|
||||
GVariant *ret;
|
||||
GError *error = NULL;
|
||||
const gchar *client_path;
|
||||
|
||||
ret = g_dbus_proxy_call_finish (priv->daemon, res, &error);
|
||||
if (ret == NULL) {
|
||||
g_warning ("failed to connect client: %s", error->message);
|
||||
context_set_state (context, PINOS_CONTEXT_STATE_ERROR, error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_get (ret, "(&o)", &client_path);
|
||||
|
||||
pinos_subscribe_get_proxy (priv->subscribe,
|
||||
PINOS_DBUS_SERVICE,
|
||||
client_path,
|
||||
"org.pinos.Client1",
|
||||
NULL,
|
||||
on_client_proxy,
|
||||
context);
|
||||
g_variant_unref (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
on_daemon_connected (GObject *source_object,
|
||||
|
|
@ -440,21 +383,9 @@ on_daemon_connected (GObject *source_object,
|
|||
gpointer user_data)
|
||||
{
|
||||
PinosContext *context = user_data;
|
||||
PinosContextPrivate *priv = context->priv;
|
||||
GVariant *variant;
|
||||
|
||||
context_set_state (context, PINOS_CONTEXT_STATE_REGISTERING, NULL);
|
||||
|
||||
variant = pinos_properties_to_variant (priv->properties);
|
||||
|
||||
g_dbus_proxy_call (priv->daemon,
|
||||
"ConnectClient",
|
||||
g_variant_new ("(@a{sv})", variant),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
on_client_connected,
|
||||
context);
|
||||
context_set_state (context, PINOS_CONTEXT_STATE_READY, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -472,22 +403,6 @@ subscription_cb (PinosSubscribe *subscribe,
|
|||
priv->daemon = g_object_ref (object);
|
||||
break;
|
||||
|
||||
case PINOS_SUBSCRIPTION_FLAG_CLIENT:
|
||||
if (event == PINOS_SUBSCRIPTION_EVENT_NEW) {
|
||||
priv->clients = g_list_prepend (priv->clients, object);
|
||||
} else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) {
|
||||
priv->clients = g_list_remove (priv->clients, object);
|
||||
|
||||
if (object == priv->client && !priv->disconnecting) {
|
||||
context_set_state (context,
|
||||
PINOS_CONTEXT_STATE_ERROR,
|
||||
g_error_new_literal (G_IO_ERROR,
|
||||
G_IO_ERROR_CLOSED,
|
||||
"Client disappeared"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PINOS_SUBSCRIPTION_FLAG_NODE:
|
||||
if (event == PINOS_SUBSCRIPTION_EVENT_NEW)
|
||||
priv->nodes = g_list_prepend (priv->nodes, object);
|
||||
|
|
@ -628,62 +543,18 @@ pinos_context_connect (PinosContext *context,
|
|||
}
|
||||
|
||||
static void
|
||||
finish_client_disconnect (PinosContext *context)
|
||||
do_disconnect (PinosContext *context)
|
||||
{
|
||||
PinosContextPrivate *priv = context->priv;
|
||||
|
||||
g_clear_object (&priv->client);
|
||||
g_clear_object (&priv->daemon);
|
||||
if (priv->id) {
|
||||
g_bus_unwatch_name(priv->id);
|
||||
priv->id = 0;
|
||||
}
|
||||
|
||||
context_set_state (context, PINOS_CONTEXT_STATE_UNCONNECTED, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_disconnected (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosContext *context = user_data;
|
||||
PinosContextPrivate *priv = context->priv;
|
||||
GError *error = NULL;
|
||||
GVariant *ret;
|
||||
|
||||
priv->disconnecting = FALSE;
|
||||
|
||||
ret = g_dbus_proxy_call_finish (priv->client, res, &error);
|
||||
if (ret == NULL) {
|
||||
g_warning ("failed to disconnect client: %s", error->message);
|
||||
context_set_state (context, PINOS_CONTEXT_STATE_ERROR, error);
|
||||
g_object_unref (context);
|
||||
return;
|
||||
}
|
||||
g_variant_unref (ret);
|
||||
|
||||
finish_client_disconnect (context);
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_disconnect (PinosContext *context)
|
||||
{
|
||||
PinosContextPrivate *priv = context->priv;
|
||||
|
||||
g_dbus_proxy_call (priv->client,
|
||||
"Disconnect",
|
||||
g_variant_new ("()"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
on_client_disconnected,
|
||||
context);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_context_disconnect:
|
||||
* @context: a #PinosContext
|
||||
|
|
@ -702,11 +573,6 @@ pinos_context_disconnect (PinosContext *context)
|
|||
priv = context->priv;
|
||||
g_return_val_if_fail (!priv->disconnecting, FALSE);
|
||||
|
||||
if (priv->client == NULL) {
|
||||
finish_client_disconnect (context);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
priv->disconnecting = TRUE;
|
||||
|
||||
g_main_context_invoke (priv->context,
|
||||
|
|
@ -756,6 +622,7 @@ pinos_context_get_error (PinosContext *context)
|
|||
}
|
||||
|
||||
typedef struct {
|
||||
gchar *factory_name;
|
||||
gchar *name;
|
||||
PinosProperties *properties;
|
||||
} CreateNodeData;
|
||||
|
|
@ -763,6 +630,7 @@ typedef struct {
|
|||
static void
|
||||
create_node_data_free (CreateNodeData *data)
|
||||
{
|
||||
g_free (data->factory_name);
|
||||
g_free (data->name);
|
||||
if (data->properties)
|
||||
pinos_properties_free (data->properties);
|
||||
|
|
@ -786,10 +654,7 @@ on_node_proxy (GObject *source_object,
|
|||
if (proxy == NULL)
|
||||
goto node_failed;
|
||||
|
||||
node = g_object_new (PINOS_TYPE_CLIENT_NODE,
|
||||
"context", context,
|
||||
"proxy", proxy,
|
||||
NULL);
|
||||
node = pinos_client_node_new (context, proxy);
|
||||
|
||||
g_task_return_pointer (task, node, (GDestroyNotify) g_object_unref);
|
||||
g_object_unref (task);
|
||||
|
|
@ -805,7 +670,6 @@ node_failed:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
on_node_created (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
|
|
@ -817,9 +681,9 @@ on_node_created (GObject *source_object,
|
|||
GError *error = NULL;
|
||||
const gchar *node_path;
|
||||
|
||||
g_assert (context->priv->client == G_DBUS_PROXY (source_object));
|
||||
g_assert (context->priv->daemon == G_DBUS_PROXY (source_object));
|
||||
|
||||
ret = g_dbus_proxy_call_finish (context->priv->client, res, &error);
|
||||
ret = g_dbus_proxy_call_finish (context->priv->daemon, res, &error);
|
||||
if (ret == NULL)
|
||||
goto create_failed;
|
||||
|
||||
|
|
@ -853,10 +717,11 @@ do_create_node (GTask *task)
|
|||
PinosContext *context = g_task_get_source_object (task);
|
||||
CreateNodeData *data = g_task_get_task_data (task);
|
||||
|
||||
g_dbus_proxy_call (context->priv->client,
|
||||
g_dbus_proxy_call (context->priv->daemon,
|
||||
"CreateNode",
|
||||
g_variant_new ("(s@a{sv})",
|
||||
"client-node",
|
||||
g_variant_new ("(ss@a{sv})",
|
||||
data->factory_name,
|
||||
data->name,
|
||||
pinos_properties_to_variant (data->properties)),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
|
|
@ -879,16 +744,19 @@ do_create_node (GTask *task)
|
|||
*/
|
||||
void
|
||||
pinos_context_create_node (PinosContext *context,
|
||||
const gchar *factory_name,
|
||||
const gchar *name,
|
||||
PinosProperties *properties,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosContextPrivate *priv;
|
||||
GTask *task;
|
||||
CreateNodeData *data;
|
||||
|
||||
g_return_if_fail (PINOS_IS_CONTEXT (context));
|
||||
priv = context->priv;
|
||||
|
||||
task = g_task_new (context,
|
||||
cancellable,
|
||||
|
|
@ -896,8 +764,9 @@ pinos_context_create_node (PinosContext *context,
|
|||
user_data);
|
||||
|
||||
data = g_slice_new (CreateNodeData);
|
||||
data->factory_name = g_strdup (factory_name);
|
||||
data->name = g_strdup (name);
|
||||
data->properties = properties ? pinos_properties_copy (properties) : NULL;
|
||||
data->properties = pinos_properties_merge (priv->properties, properties);
|
||||
|
||||
g_task_set_task_data (task, data, (GDestroyNotify) create_node_data_free);
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ gboolean pinos_context_connect (PinosContext *context, Pi
|
|||
gboolean pinos_context_disconnect (PinosContext *context);
|
||||
|
||||
void pinos_context_create_node (PinosContext *context,
|
||||
const gchar *factory_name,
|
||||
const gchar *name,
|
||||
PinosProperties *properties,
|
||||
GCancellable *cancellable,
|
||||
|
|
|
|||
|
|
@ -165,114 +165,6 @@ pinos_context_get_daemon_info (PinosContext *context,
|
|||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
client_fill_info (PinosClientInfo *info, GDBusProxy *proxy)
|
||||
{
|
||||
GHashTable *changed = g_object_get_data (G_OBJECT (proxy), "pinos-changed-properties");
|
||||
|
||||
info->id = proxy;
|
||||
info->client_path = g_dbus_proxy_get_object_path (proxy);
|
||||
SET_STRING ("Sender", sender, 0);
|
||||
|
||||
info->change_mask = 0;
|
||||
SET_PROPERTIES ("Properties", properties, 0);
|
||||
|
||||
if (changed)
|
||||
g_hash_table_remove_all (changed);
|
||||
}
|
||||
|
||||
static void
|
||||
client_clear_info (PinosClientInfo *info)
|
||||
{
|
||||
if (info->properties)
|
||||
pinos_properties_free (info->properties);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pinos_context_list_client_info:
|
||||
* @context: a connected #PinosContext
|
||||
* @flags: extra #PinosClientInfoFlags
|
||||
* @cb: a #PinosClientInfoCallback
|
||||
* @cancelable: a #GCancellable
|
||||
* @callback: a #GAsyncReadyCallback to call when the operation is finished
|
||||
* @user_data: user data passed to @cb
|
||||
*
|
||||
* Call @cb for each client.
|
||||
*/
|
||||
void
|
||||
pinos_context_list_client_info (PinosContext *context,
|
||||
PinosClientInfoFlags flags,
|
||||
PinosClientInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosContextPrivate *priv;
|
||||
GList *walk;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (PINOS_IS_CONTEXT (context));
|
||||
g_return_if_fail (cb != NULL);
|
||||
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
|
||||
priv = context->priv;
|
||||
|
||||
for (walk = priv->clients; walk; walk = g_list_next (walk)) {
|
||||
GDBusProxy *proxy = walk->data;
|
||||
PinosClientInfo info;
|
||||
|
||||
client_fill_info (&info, proxy);
|
||||
cb (context, &info, user_data);
|
||||
client_clear_info (&info);
|
||||
}
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_context_get_client_info_by_id:
|
||||
* @context: a connected #PinosContext
|
||||
* @id: a client id
|
||||
* @flags: extra #PinosClientInfoFlags
|
||||
* @cb: a #PinosClientInfoCallback
|
||||
* @cancelable: a #GCancellable
|
||||
* @callback: a #GAsyncReadyCallback to call when the operation is finished
|
||||
* @user_data: user data passed to @cb
|
||||
*
|
||||
* Call @cb for the client with @id.
|
||||
*/
|
||||
void
|
||||
pinos_context_get_client_info_by_id (PinosContext *context,
|
||||
gpointer id,
|
||||
PinosClientInfoFlags flags,
|
||||
PinosClientInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosClientInfo info;
|
||||
GDBusProxy *proxy;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (PINOS_IS_CONTEXT (context));
|
||||
g_return_if_fail (id != NULL);
|
||||
g_return_if_fail (cb != NULL);
|
||||
|
||||
task = g_task_new (context, cancellable, callback, user_data);
|
||||
|
||||
proxy = G_DBUS_PROXY (id);
|
||||
|
||||
client_fill_info (&info, proxy);
|
||||
cb (context, &info, user_data);
|
||||
client_clear_info (&info);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_state_as_string:
|
||||
* @state: a #PinosNodeeState
|
||||
|
|
@ -299,6 +191,7 @@ node_fill_info (PinosNodeInfo *info, GDBusProxy *proxy)
|
|||
|
||||
info->id = proxy;
|
||||
info->node_path = g_dbus_proxy_get_object_path (proxy);
|
||||
SET_STRING ("Owner", owner, 0);
|
||||
|
||||
info->change_mask = 0;
|
||||
SET_STRING ("Name", name, 0);
|
||||
|
|
|
|||
|
|
@ -144,66 +144,11 @@ void pinos_context_get_daemon_info (PinosContext *context,
|
|||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* PinosClientInfo:
|
||||
* @id: generic id of the client
|
||||
* @client_path: unique path of the client
|
||||
* @sender: sender of client
|
||||
* @change_mask: bitfield of changed fields since last call
|
||||
* @properties: extra properties
|
||||
*
|
||||
* The client information. Extra information can be added in later
|
||||
* versions.
|
||||
*/
|
||||
typedef struct {
|
||||
gpointer id;
|
||||
const char *client_path;
|
||||
const char *sender;
|
||||
guint64 change_mask;
|
||||
PinosProperties *properties;
|
||||
} PinosClientInfo;
|
||||
|
||||
/**
|
||||
* PinosClientInfoFlags:
|
||||
* @PINOS_CLIENT_INFO_FLAGS_NONE: no flags
|
||||
*
|
||||
* Extra flags for pinos_context_list_client_info() and
|
||||
* pinos_context_get_client_info_by_id().
|
||||
*/
|
||||
typedef enum {
|
||||
PINOS_CLIENT_INFO_FLAGS_NONE = 0,
|
||||
} PinosClientInfoFlags;
|
||||
|
||||
/**
|
||||
* PinosClientInfoCallback:
|
||||
* @c: a #PinosContext
|
||||
* @info: a #PinosClientInfo
|
||||
* @user_data: user data
|
||||
*
|
||||
* Callback with information about the Pinos client in @info.
|
||||
*/
|
||||
typedef void (*PinosClientInfoCallback) (PinosContext *c,
|
||||
const PinosClientInfo *info,
|
||||
gpointer user_data);
|
||||
|
||||
void pinos_context_list_client_info (PinosContext *context,
|
||||
PinosClientInfoFlags flags,
|
||||
PinosClientInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
void pinos_context_get_client_info_by_id (PinosContext *context,
|
||||
gpointer id,
|
||||
PinosClientInfoFlags flags,
|
||||
PinosClientInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* PinosNodeInfo:
|
||||
* @id: generic id of the node
|
||||
* @node_path: the unique path of the node
|
||||
* @owner: the unique name of the owner
|
||||
* @change_mask: bitfield of changed fields since last call
|
||||
* @name: name the node, suitable for display
|
||||
* @properties: the properties of the node
|
||||
|
|
@ -215,6 +160,7 @@ void pinos_context_get_client_info_by_id (PinosContext *context,
|
|||
typedef struct {
|
||||
gpointer id;
|
||||
const char *node_path;
|
||||
const char *owner;
|
||||
guint64 change_mask;
|
||||
const char *name;
|
||||
PinosProperties *properties;
|
||||
|
|
|
|||
|
|
@ -56,14 +56,16 @@ struct _PinosPortPrivate
|
|||
GBytes *format;
|
||||
PinosProperties *properties;
|
||||
|
||||
int fd;
|
||||
GSource *socket_source;
|
||||
|
||||
PinosBuffer recv_buffer;
|
||||
|
||||
guint8 recv_data[MAX_BUFFER_SIZE];
|
||||
gint recv_fds[MAX_FDS];
|
||||
int recv_fds[MAX_FDS];
|
||||
|
||||
guint8 send_data[MAX_BUFFER_SIZE];
|
||||
gint send_fds[MAX_FDS];
|
||||
int send_fds[MAX_FDS];
|
||||
|
||||
PinosBuffer *buffer;
|
||||
PinosPort *peers[16];
|
||||
|
|
@ -463,14 +465,13 @@ read_buffer (PinosPort *port,
|
|||
{
|
||||
PinosPortPrivate *priv = port->priv;
|
||||
gssize len;
|
||||
GInputVector ivec;
|
||||
PinosStackHeader *hdr;
|
||||
GSocketControlMessage **messages = NULL;
|
||||
PinosStackBuffer *sb = (PinosStackBuffer *) &priv->recv_buffer;
|
||||
gint num_messages = 0;
|
||||
gint flags = 0;
|
||||
gsize need;
|
||||
gint i;
|
||||
struct cmsghdr *cmsg;
|
||||
struct msghdr msg = {0};
|
||||
struct iovec iov[1];
|
||||
char cmsgbuf[CMSG_SPACE (MAX_FDS * sizeof (int))];
|
||||
|
||||
g_assert (sb->refcount == 0);
|
||||
|
||||
|
|
@ -479,28 +480,31 @@ read_buffer (PinosPort *port,
|
|||
sb->size = 0;
|
||||
sb->free_data = NULL;
|
||||
sb->fds = priv->recv_fds;
|
||||
sb->max_fds = MAX_FDS;
|
||||
sb->max_fds = 0;
|
||||
sb->n_fds = 0;
|
||||
sb->free_fds = NULL;
|
||||
|
||||
hdr = sb->data;
|
||||
|
||||
/* read header first */
|
||||
ivec.buffer = hdr;
|
||||
ivec.size = sizeof (PinosStackHeader);
|
||||
|
||||
len = g_socket_receive_message (priv->sockets[0],
|
||||
NULL,
|
||||
&ivec,
|
||||
1,
|
||||
&messages,
|
||||
&num_messages,
|
||||
&flags,
|
||||
NULL,
|
||||
error);
|
||||
if (len == -1)
|
||||
return NULL;
|
||||
/* read header and control messages first */
|
||||
iov[0].iov_base = hdr;
|
||||
iov[0].iov_len = sizeof (PinosStackHeader);;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = sizeof (cmsgbuf);
|
||||
msg.msg_flags = MSG_CMSG_CLOEXEC;
|
||||
|
||||
while (TRUE) {
|
||||
len = recvmsg (priv->fd, &msg, msg.msg_flags);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
goto recv_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
g_assert (len == sizeof (PinosStackHeader));
|
||||
|
||||
/* now we know the total length */
|
||||
|
|
@ -515,103 +519,94 @@ read_buffer (PinosPort *port,
|
|||
|
||||
if (hdr->length > 0) {
|
||||
/* read data */
|
||||
len = g_socket_receive (priv->sockets[0],
|
||||
(gchar *)sb->data + sizeof (PinosStackHeader),
|
||||
hdr->length,
|
||||
NULL,
|
||||
error);
|
||||
if (len == -1)
|
||||
return NULL;
|
||||
|
||||
while (TRUE) {
|
||||
len = recv (priv->fd, (gchar *)sb->data + sizeof (PinosStackHeader), hdr->length, 0);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
goto recv_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
g_assert (len == hdr->length);
|
||||
}
|
||||
|
||||
if (sb->max_fds < num_messages) {
|
||||
g_warning ("port %p: realloc receive fds %d -> %d", port, sb->max_fds, num_messages);
|
||||
sb->max_fds = num_messages;
|
||||
sb->fds = sb->free_fds = g_realloc (sb->free_fds, num_messages * sizeof (int));
|
||||
}
|
||||
|
||||
/* handle control messages */
|
||||
for (i = 0; i < num_messages; i++) {
|
||||
GSocketControlMessage *msg = messages[i];
|
||||
gint *fds, n_fds, j;
|
||||
|
||||
if (g_socket_control_message_get_msg_type (msg) != SCM_RIGHTS)
|
||||
for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; cmsg = CMSG_NXTHDR (&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
|
||||
continue;
|
||||
|
||||
fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (msg), &n_fds);
|
||||
for (j = 0; j < n_fds; j++)
|
||||
sb->fds[i] = fds[i];
|
||||
sb->n_fds = n_fds;
|
||||
g_free (fds);
|
||||
g_object_unref (msg);
|
||||
sb->n_fds = (cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg)) / sizeof (int);
|
||||
memcpy (sb->fds, CMSG_DATA (cmsg), sb->n_fds * sizeof (int));
|
||||
}
|
||||
g_free (messages);
|
||||
|
||||
sb->refcount = 1;
|
||||
sb->magic = PSB_MAGIC;
|
||||
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: buffer %p init", &priv->recv_buffer, sb);
|
||||
|
||||
return &priv->recv_buffer;
|
||||
|
||||
/* ERRORS */
|
||||
recv_error:
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_errno (errno),
|
||||
"could not recvmsg: %s", strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
write_buffer (GSocket *socket,
|
||||
write_buffer (PinosPort *port,
|
||||
PinosBuffer *buffer,
|
||||
GError **error)
|
||||
{
|
||||
gssize len;
|
||||
PinosPortPrivate *priv = port->priv;
|
||||
PinosStackBuffer *sb = (PinosStackBuffer *) buffer;
|
||||
GOutputVector ovec[1];
|
||||
GSocketControlMessage *msg = NULL;
|
||||
gint n_msg, i, flags = 0;
|
||||
gssize len;
|
||||
struct msghdr msg = {0};
|
||||
struct iovec iov[1];
|
||||
struct cmsghdr *cmsg;
|
||||
char cmsgbuf[CMSG_SPACE (MAX_FDS * sizeof (int))];
|
||||
gint fds_len = sb->n_fds * sizeof (int);
|
||||
|
||||
g_return_val_if_fail (buffer != NULL, FALSE);
|
||||
iov[0].iov_base = sb->data;
|
||||
iov[0].iov_len = sb->size;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = CMSG_SPACE (fds_len);
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN (fds_len);
|
||||
memcpy(CMSG_DATA(cmsg), sb->fds, fds_len);
|
||||
msg.msg_controllen = cmsg->cmsg_len;
|
||||
|
||||
ovec[0].buffer = sb->data;
|
||||
ovec[0].size = sb->size;
|
||||
|
||||
if (sb->n_fds) {
|
||||
msg = g_unix_fd_message_new ();
|
||||
for (i = 0; i < sb->n_fds; i++) {
|
||||
if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (msg), sb->fds[i], error))
|
||||
goto append_failed;
|
||||
while (TRUE) {
|
||||
len = sendmsg (priv->fd, &msg, 0);
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
goto send_error;
|
||||
}
|
||||
n_msg = 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
n_msg = 0;
|
||||
}
|
||||
|
||||
len = g_socket_send_message (socket,
|
||||
NULL,
|
||||
ovec,
|
||||
1,
|
||||
&msg,
|
||||
n_msg,
|
||||
flags,
|
||||
NULL,
|
||||
error);
|
||||
g_clear_object (&msg);
|
||||
|
||||
if (len == -1)
|
||||
goto send_error;
|
||||
|
||||
g_assert (len == (gssize) sb->size);
|
||||
|
||||
return TRUE;
|
||||
|
||||
append_failed:
|
||||
{
|
||||
g_warning ("failed to append fd: %s", error ? (*error)->message : "unknown reason" );
|
||||
return FALSE;
|
||||
}
|
||||
/* ERRORS */
|
||||
send_error:
|
||||
{
|
||||
g_warning ("failed to send message: %s", error ? (*error)->message : "unknown reason" );
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_errno (errno),
|
||||
"could not sendmsg: %s", strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -661,7 +656,7 @@ pinos_port_receive_buffer (PinosPort *port,
|
|||
|
||||
if (priv->sockets[0]) {
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: write buffer %p", port, buffer);
|
||||
res = write_buffer (priv->sockets[0], buffer, error);
|
||||
res = write_buffer (port, buffer, error);
|
||||
}
|
||||
else {
|
||||
res = TRUE;
|
||||
|
|
@ -750,6 +745,7 @@ handle_socket (PinosPort *port, GSocket *socket)
|
|||
GMainContext *context = g_main_context_get_thread_default();
|
||||
|
||||
g_debug ("port %p: handle socket in context %p", port, context);
|
||||
priv->fd = g_socket_get_fd (socket);
|
||||
priv->socket_source = g_socket_create_source (socket, G_IO_IN, NULL);
|
||||
g_source_set_callback (priv->socket_source, (GSourceFunc) on_socket_condition, port, NULL);
|
||||
g_source_attach (priv->socket_source, context);
|
||||
|
|
@ -764,6 +760,7 @@ unhandle_socket (PinosPort *port)
|
|||
if (priv->socket_source) {
|
||||
g_source_destroy (priv->socket_source);
|
||||
g_clear_pointer (&priv->socket_source, g_source_unref);
|
||||
priv->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -819,6 +816,7 @@ pinos_port_send_buffer (PinosPort *port,
|
|||
PinosPort *peer;
|
||||
gboolean res = TRUE;
|
||||
gint i;
|
||||
GError *err = NULL;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_PORT (port), FALSE);
|
||||
priv = port->priv;
|
||||
|
|
@ -829,14 +827,20 @@ pinos_port_send_buffer (PinosPort *port,
|
|||
PINOS_DEBUG_TRANSPORT ("port %p: send buffer %p", port, buffer);
|
||||
if (priv->sockets[0]) {
|
||||
PINOS_DEBUG_TRANSPORT ("port %p: write buffer %p", port, buffer);
|
||||
res = write_buffer (priv->sockets[0], buffer, error);
|
||||
res = write_buffer (port, buffer, &err);
|
||||
}
|
||||
for (i = 0; i < priv->n_peers; i++) {
|
||||
peer = priv->peers[i];
|
||||
if (peer == NULL)
|
||||
continue;
|
||||
res = pinos_port_receive_buffer (peer, buffer, error);
|
||||
res = pinos_port_receive_buffer (peer, buffer, &err);
|
||||
}
|
||||
if (!res) {
|
||||
if (error == NULL)
|
||||
g_warning ("could not send buffer: %s", err->message);
|
||||
g_propagate_error (error, err);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,13 +33,11 @@ struct _PinosContextPrivate
|
|||
GError *error;
|
||||
|
||||
GDBusProxy *daemon;
|
||||
GDBusProxy *client;
|
||||
gboolean disconnecting;
|
||||
|
||||
PinosSubscriptionFlags subscription_mask;
|
||||
PinosSubscribe *subscribe;
|
||||
|
||||
GList *clients;
|
||||
GList *nodes;
|
||||
GList *ports;
|
||||
GList *connections;
|
||||
|
|
|
|||
|
|
@ -82,6 +82,33 @@ pinos_properties_copy (PinosProperties *properties)
|
|||
return copy;
|
||||
}
|
||||
|
||||
PinosProperties *
|
||||
pinos_properties_merge (PinosProperties *oldprops,
|
||||
PinosProperties *newprops)
|
||||
{
|
||||
PinosProperties *res = NULL;
|
||||
|
||||
if (oldprops == NULL) {
|
||||
if (newprops == NULL)
|
||||
res = NULL;
|
||||
else
|
||||
res = pinos_properties_copy (newprops);
|
||||
} else if (newprops == NULL) {
|
||||
res = pinos_properties_copy (oldprops);
|
||||
} else {
|
||||
const gchar *key;
|
||||
gpointer state = NULL;
|
||||
|
||||
res = pinos_properties_copy (oldprops);
|
||||
while ((key = pinos_properties_iterate (newprops, &state))) {
|
||||
pinos_properties_set (res,
|
||||
key,
|
||||
pinos_properties_get (newprops, key));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_properties_free:
|
||||
* @properties: a #PinosProperties
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ GType pinos_properties_get_type (void);
|
|||
|
||||
PinosProperties * pinos_properties_new (const gchar *key, ...) G_GNUC_NULL_TERMINATED;
|
||||
PinosProperties * pinos_properties_copy (PinosProperties *properties);
|
||||
PinosProperties * pinos_properties_merge (PinosProperties *oldprops,
|
||||
PinosProperties *newprops);
|
||||
void pinos_properties_free (PinosProperties *properties);
|
||||
|
||||
void pinos_properties_set (PinosProperties *properties,
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@ do_connect (PinosStream *stream)
|
|||
PinosContext *context = priv->context;
|
||||
|
||||
pinos_context_create_node (context,
|
||||
"client-node",
|
||||
"client-node",
|
||||
priv->properties,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
|
|
|
|||
|
|
@ -102,9 +102,6 @@ notify_event (PinosSubscribe *subscribe,
|
|||
if (g_strcmp0 (interface_name, "org.pinos.Daemon1") == 0) {
|
||||
flags = PINOS_SUBSCRIPTION_FLAG_DAEMON;
|
||||
}
|
||||
else if (g_strcmp0 (interface_name, "org.pinos.Client1") == 0) {
|
||||
flags = PINOS_SUBSCRIPTION_FLAG_CLIENT;
|
||||
}
|
||||
else if (g_strcmp0 (interface_name, "org.pinos.Node1") == 0) {
|
||||
flags = PINOS_SUBSCRIPTION_FLAG_NODE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,12 +46,11 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
PINOS_SUBSCRIPTION_FLAG_DAEMON = (1 << 0),
|
||||
PINOS_SUBSCRIPTION_FLAG_CLIENT = (1 << 1),
|
||||
PINOS_SUBSCRIPTION_FLAG_NODE = (1 << 2),
|
||||
PINOS_SUBSCRIPTION_FLAG_PORT = (1 << 3)
|
||||
PINOS_SUBSCRIPTION_FLAG_NODE = (1 << 1),
|
||||
PINOS_SUBSCRIPTION_FLAG_PORT = (1 << 2)
|
||||
} PinosSubscriptionFlags;
|
||||
|
||||
#define PINOS_SUBSCRIPTION_FLAGS_ALL 0x0f
|
||||
#define PINOS_SUBSCRIPTION_FLAGS_ALL 0x07
|
||||
|
||||
typedef enum {
|
||||
PINOS_SUBSCRIPTION_EVENT_NEW = 0,
|
||||
|
|
|
|||
|
|
@ -22,63 +22,21 @@
|
|||
<property name='Cookie' type='u' access='read' />
|
||||
<!-- Properties: Extra properties of the daemon -->
|
||||
<property name='Properties' type='a{sv}' access='read' />
|
||||
<!-- ConnectClient:
|
||||
@properties: properties of the client
|
||||
@client: a new client object
|
||||
|
||||
Register a client to the pinos daemon. A new client object
|
||||
will be generated that should be used to perform any other
|
||||
action on the server.
|
||||
-->
|
||||
<method name='ConnectClient'>
|
||||
<arg type='a{sv}' name='properties' direction='in'/>
|
||||
<arg type='o' name='client' direction='out'/>
|
||||
</method>
|
||||
</interface>
|
||||
|
||||
<!--
|
||||
org.pinos.Client1:
|
||||
@short_description: Main client interface
|
||||
|
||||
Interface obtained after connecting a client and allows for
|
||||
obtaining an channel object from a source/sink.
|
||||
-->
|
||||
<interface name='org.pinos.Client1'>
|
||||
<!-- Sender: Sender of the client -->
|
||||
<property name='Sender' type='s' access='read' />
|
||||
<!-- Name: Properties of the client -->
|
||||
<property name='Properties' type='a{sv}' access='read' />
|
||||
<!-- Disconnect:
|
||||
|
||||
Disconnect the client from the server.
|
||||
-->
|
||||
<method name='Disconnect'/>
|
||||
<!-- CreateNode:
|
||||
@factory_name: the factory name to use for the node
|
||||
@name: the name of the node
|
||||
@properties: extra properties
|
||||
@Properties: extra properties
|
||||
@node: the Node1 object path
|
||||
|
||||
Create a new Node with given name and properties
|
||||
-->
|
||||
<method name='CreateNode'>
|
||||
<arg type='s' name='Name' direction='in' />
|
||||
<arg type='s' name='factory_name' direction='in' />
|
||||
<arg type='s' name='name' direction='in' />
|
||||
<arg type='a{sv}' name='properties' direction='in'/>
|
||||
<arg type='o' name='node' direction='out'/>
|
||||
</method>
|
||||
|
||||
<!-- CreateUploadChannel:
|
||||
@possible_formats: the formats that can be provided
|
||||
@properties: extra properties
|
||||
@channel: the Channel object path
|
||||
|
||||
Create a new channel to upload a new stream
|
||||
-->
|
||||
<method name='CreateUploadChannel'>
|
||||
<arg type='s' name='possible_formats' direction='in'/>
|
||||
<arg type='a{sv}' name='properties' direction='in'/>
|
||||
<arg type='o' name='channel' direction='out'/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
|
||||
<!--
|
||||
|
|
@ -91,7 +49,7 @@
|
|||
<!-- Name: the name of the node -->
|
||||
<property name='Name' type='s' access='read' />
|
||||
<!-- Owner: the owner path of this node -->
|
||||
<property name='Owner' type='o' access='read' />
|
||||
<property name='Owner' type='s' access='read' />
|
||||
<!-- Properties: extra node properties -->
|
||||
<property name='Properties' type='a{sv}' access='read' />
|
||||
<!-- state: state of the node
|
||||
|
|
|
|||
|
|
@ -1,432 +0,0 @@
|
|||
/* Pinos
|
||||
* 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 <string.h>
|
||||
#include "pinos/client/pinos.h"
|
||||
|
||||
#include "pinos/server/client.h"
|
||||
#include "pinos/server/server-node.h"
|
||||
#include "pinos/server/upload-node.h"
|
||||
|
||||
#include "pinos/dbus/org-pinos.h"
|
||||
|
||||
struct _PinosClientPrivate
|
||||
{
|
||||
PinosDaemon *daemon;
|
||||
PinosClient1 *iface;
|
||||
|
||||
gchar *sender;
|
||||
gchar *object_path;
|
||||
PinosProperties *properties;
|
||||
|
||||
PinosFdManager *fdmanager;
|
||||
|
||||
GList *nodes;
|
||||
};
|
||||
|
||||
#define PINOS_CLIENT_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_CLIENT, PinosClientPrivate))
|
||||
|
||||
G_DEFINE_TYPE (PinosClient, pinos_client, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DAEMON,
|
||||
PROP_SENDER,
|
||||
PROP_OBJECT_PATH,
|
||||
PROP_PROPERTIES,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_DISCONNECT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
pinos_client_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PinosClient *client = PINOS_CLIENT (_object);
|
||||
PinosClientPrivate *priv = client->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DAEMON:
|
||||
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;
|
||||
|
||||
case PROP_PROPERTIES:
|
||||
g_value_set_boxed (value, priv->properties);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_client_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PinosClient *client = PINOS_CLIENT (_object);
|
||||
PinosClientPrivate *priv = client->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DAEMON:
|
||||
priv->daemon = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_SENDER:
|
||||
priv->sender = g_value_dup_string (value);
|
||||
pinos_client1_set_sender (priv->iface, priv->sender);
|
||||
break;
|
||||
|
||||
case PROP_PROPERTIES:
|
||||
if (priv->properties)
|
||||
pinos_properties_free (priv->properties);
|
||||
priv->properties = g_value_dup_boxed (value);
|
||||
pinos_client1_set_properties (priv->iface, priv->properties ?
|
||||
pinos_properties_to_variant (priv->properties) : NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_remove_node (PinosNode *node,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosClient *client = user_data;
|
||||
PinosClientPrivate *priv = client->priv;
|
||||
|
||||
g_debug ("client %p: remove node %p", client, node);
|
||||
priv->nodes = g_list_remove (priv->nodes, node);
|
||||
g_object_unref (node);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_create_node (PinosClient1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar *arg_name,
|
||||
GVariant *arg_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosClient *client = user_data;
|
||||
PinosClientPrivate *priv = client->priv;
|
||||
PinosNode *node;
|
||||
const gchar *object_path, *sender;
|
||||
PinosProperties *props;
|
||||
|
||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
if (g_strcmp0 (pinos_client_get_sender (client), sender) != 0)
|
||||
goto not_allowed;
|
||||
|
||||
props = pinos_properties_from_variant (arg_properties);
|
||||
node = pinos_server_node_new (priv->daemon,
|
||||
sender,
|
||||
arg_name,
|
||||
props);
|
||||
pinos_properties_free (props);
|
||||
|
||||
if (node == NULL)
|
||||
goto no_node;
|
||||
|
||||
priv->nodes = g_list_prepend (priv->nodes, node);
|
||||
|
||||
g_signal_connect (node,
|
||||
"remove",
|
||||
(GCallback) handle_remove_node,
|
||||
client);
|
||||
|
||||
object_path = pinos_server_node_get_object_path (PINOS_SERVER_NODE (node));
|
||||
g_debug ("client %p: add node %p %d, %s", client, node, G_OBJECT (node)->ref_count, object_path);
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(o)", object_path));
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
not_allowed:
|
||||
{
|
||||
g_debug ("sender %s is not owner of client object %s", sender, pinos_client_get_sender (client));
|
||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
||||
"org.pinos.Error", "sender not client owner");
|
||||
return TRUE;
|
||||
}
|
||||
no_node:
|
||||
{
|
||||
g_debug ("client %p: could create node %s", client, arg_name);
|
||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
||||
"org.pinos.Error", "can't create node");
|
||||
pinos_properties_free (props);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_disconnect (PinosClient1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosClient *client = user_data;
|
||||
|
||||
g_debug ("client %p: disconnect", client);
|
||||
g_signal_emit (client, signals[SIGNAL_DISCONNECT], 0, NULL);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("()"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
client_register_object (PinosClient *client)
|
||||
{
|
||||
PinosClientPrivate *priv = client->priv;
|
||||
PinosDaemon *daemon = priv->daemon;
|
||||
PinosObjectSkeleton *skel;
|
||||
|
||||
skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_CLIENT);
|
||||
|
||||
pinos_object_skeleton_set_client1 (skel, priv->iface);
|
||||
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel));
|
||||
g_object_unref (skel);
|
||||
|
||||
g_debug ("client %p: register %s", client, priv->object_path);
|
||||
}
|
||||
|
||||
static void
|
||||
client_unregister_object (PinosClient *client)
|
||||
{
|
||||
PinosClientPrivate *priv = client->priv;
|
||||
PinosDaemon *daemon = priv->daemon;
|
||||
|
||||
g_debug ("client %p: unregister", client);
|
||||
pinos_daemon_unexport (daemon, priv->object_path);
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_client_dispose (GObject * object)
|
||||
{
|
||||
PinosClient *client = PINOS_CLIENT (object);
|
||||
PinosClientPrivate *priv = client->priv;
|
||||
GList *copy;
|
||||
|
||||
g_debug ("client %p: dispose", client);
|
||||
pinos_fd_manager_remove_all (priv->fdmanager, priv->object_path);
|
||||
|
||||
copy = g_list_copy (priv->nodes);
|
||||
g_list_free_full (copy, (GDestroyNotify) pinos_node_remove);
|
||||
client_unregister_object (client);
|
||||
|
||||
G_OBJECT_CLASS (pinos_client_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_client_finalize (GObject * object)
|
||||
{
|
||||
PinosClient *client = PINOS_CLIENT (object);
|
||||
PinosClientPrivate *priv = client->priv;
|
||||
|
||||
g_debug ("client %p: finalize", client);
|
||||
g_clear_object (&priv->daemon);
|
||||
g_clear_object (&priv->iface);
|
||||
g_free (priv->sender);
|
||||
g_free (priv->object_path);
|
||||
if (priv->properties)
|
||||
pinos_properties_free (priv->properties);
|
||||
g_clear_object (&priv->fdmanager);
|
||||
|
||||
G_OBJECT_CLASS (pinos_client_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_client_constructed (GObject * object)
|
||||
{
|
||||
PinosClient *client = PINOS_CLIENT (object);
|
||||
|
||||
g_debug ("client %p: constructed", client);
|
||||
client_register_object (client);
|
||||
|
||||
G_OBJECT_CLASS (pinos_client_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_client_class_init (PinosClientClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PinosClientPrivate));
|
||||
|
||||
gobject_class->constructed = pinos_client_constructed;
|
||||
gobject_class->dispose = pinos_client_dispose;
|
||||
gobject_class->finalize = pinos_client_finalize;
|
||||
gobject_class->set_property = pinos_client_set_property;
|
||||
gobject_class->get_property = pinos_client_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DAEMON,
|
||||
g_param_spec_object ("daemon",
|
||||
"Daemon",
|
||||
"The daemon",
|
||||
PINOS_TYPE_DAEMON,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
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",
|
||||
"The object path",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PROPERTIES,
|
||||
g_param_spec_boxed ("properties",
|
||||
"Properties",
|
||||
"Client properties",
|
||||
PINOS_TYPE_PROPERTIES,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
signals[SIGNAL_DISCONNECT] = g_signal_new ("disconnect",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_generic,
|
||||
G_TYPE_NONE,
|
||||
0,
|
||||
G_TYPE_NONE);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_client_init (PinosClient * client)
|
||||
{
|
||||
PinosClientPrivate *priv = client->priv = PINOS_CLIENT_GET_PRIVATE (client);
|
||||
|
||||
priv->iface = pinos_client1_skeleton_new ();
|
||||
g_signal_connect (priv->iface, "handle-create-node",
|
||||
(GCallback) handle_create_node,
|
||||
client);
|
||||
g_signal_connect (priv->iface, "handle-disconnect",
|
||||
(GCallback) handle_disconnect,
|
||||
client);
|
||||
|
||||
g_debug ("client %p: new", client);
|
||||
priv->fdmanager = pinos_fd_manager_get (PINOS_FD_MANAGER_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pinos_client_new:
|
||||
* @daemon: a #PinosDaemon
|
||||
* @sender: the sender id
|
||||
* @prefix: a prefix
|
||||
* @properties: extra client properties
|
||||
*
|
||||
* Make a new #PinosClient object and register it to @daemon under the @prefix.
|
||||
*
|
||||
* Returns: a new #PinosClient
|
||||
*/
|
||||
PinosClient *
|
||||
pinos_client_new (PinosDaemon *daemon,
|
||||
const gchar *sender,
|
||||
PinosProperties *properties)
|
||||
{
|
||||
g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL);
|
||||
|
||||
return g_object_new (PINOS_TYPE_CLIENT, "daemon", daemon,
|
||||
"sender", sender,
|
||||
"properties", properties,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_client_get_sender:
|
||||
* @client: a #PinosClient
|
||||
*
|
||||
* Get the sender of @client.
|
||||
*
|
||||
* Returns: the sender of @client
|
||||
*/
|
||||
const gchar *
|
||||
pinos_client_get_sender (PinosClient *client)
|
||||
{
|
||||
PinosClientPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_CLIENT (client), NULL);
|
||||
priv = client->priv;
|
||||
|
||||
return priv->sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_client_get_object_path:
|
||||
* @client: a #PinosClient
|
||||
*
|
||||
* Get the object path of @client.
|
||||
*
|
||||
* Returns: the object path of @client
|
||||
*/
|
||||
const gchar *
|
||||
pinos_client_get_object_path (PinosClient *client)
|
||||
{
|
||||
PinosClientPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_CLIENT (client), NULL);
|
||||
priv = client->priv;
|
||||
|
||||
return priv->object_path;
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/* Pinos
|
||||
* 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 __PINOS_CLIENT_H__
|
||||
#define __PINOS_CLIENT_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <pinos/server/daemon.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PINOS_TYPE_CLIENT (pinos_client_get_type ())
|
||||
#define PINOS_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_CLIENT))
|
||||
#define PINOS_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_CLIENT))
|
||||
#define PINOS_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_CLIENT, PinosClientClass))
|
||||
#define PINOS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_CLIENT, PinosClient))
|
||||
#define PINOS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_CLIENT, PinosClientClass))
|
||||
#define PINOS_CLIENT_CAST(obj) ((PinosClient*)(obj))
|
||||
#define PINOS_CLIENT_CLASS_CAST(klass) ((PinosClientClass*)(klass))
|
||||
|
||||
typedef struct _PinosClient PinosClient;
|
||||
typedef struct _PinosClientClass PinosClientClass;
|
||||
typedef struct _PinosClientPrivate PinosClientPrivate;
|
||||
|
||||
/**
|
||||
* PinosClient:
|
||||
*
|
||||
* Pinos client object class.
|
||||
*/
|
||||
struct _PinosClient {
|
||||
GObject object;
|
||||
|
||||
PinosClientPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PinosClientClass:
|
||||
*
|
||||
* Pinos client object class.
|
||||
*/
|
||||
struct _PinosClientClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pinos_client_get_type (void);
|
||||
|
||||
PinosClient * pinos_client_new (PinosDaemon *daemon,
|
||||
const gchar *sender,
|
||||
PinosProperties *properties);
|
||||
|
||||
const gchar * pinos_client_get_sender (PinosClient *client);
|
||||
const gchar * pinos_client_get_object_path (PinosClient *client);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PINOS_CLIENT_H__ */
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
#include "pinos/client/pinos.h"
|
||||
|
||||
#include "pinos/server/daemon.h"
|
||||
#include "pinos/server/client.h"
|
||||
#include "pinos/server/server-node.h"
|
||||
|
||||
#include "pinos/dbus/org-pinos.h"
|
||||
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
struct _PinosDaemonPrivate
|
||||
{
|
||||
PinosDaemon1 *iface;
|
||||
guint id;
|
||||
GDBusConnection *connection;
|
||||
GDBusObjectManagerServer *server_manager;
|
||||
|
|
@ -60,7 +61,7 @@ typedef struct {
|
|||
} SenderData;
|
||||
|
||||
static void
|
||||
client_name_appeared_handler (GDBusConnection *connection,
|
||||
sender_name_appeared_handler (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
gpointer user_data)
|
||||
|
|
@ -74,7 +75,7 @@ client_name_appeared_handler (GDBusConnection *connection,
|
|||
}
|
||||
|
||||
static void
|
||||
client_name_vanished_handler (GDBusConnection *connection,
|
||||
sender_name_vanished_handler (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
|
@ -111,70 +112,90 @@ sender_data_new (PinosDaemon *daemon,
|
|||
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,
|
||||
sender_name_appeared_handler,
|
||||
sender_name_vanished_handler,
|
||||
data,
|
||||
(GDestroyNotify) data_free);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_disconnect_client (PinosClient *client,
|
||||
gpointer user_data)
|
||||
handle_remove_node (PinosServerNode *node,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosDaemon *daemon = user_data;
|
||||
PinosDaemonPrivate *priv = daemon->priv;
|
||||
const gchar *sender;
|
||||
SenderData *data;
|
||||
|
||||
sender = pinos_client_get_sender (client);
|
||||
sender = pinos_server_node_get_sender (node);
|
||||
|
||||
g_debug ("daemon %p: client %p disconnect %s", daemon, client, sender);
|
||||
g_debug ("daemon %p: sender %s removed node %p", daemon, sender, node);
|
||||
|
||||
data = g_hash_table_lookup (priv->senders, sender);
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
g_debug ("daemon %p: client %p unref", daemon, client);
|
||||
data->objects = g_list_remove (data->objects, client);
|
||||
g_object_unref (client);
|
||||
g_debug ("daemon %p: node %p unref", daemon, node);
|
||||
data->objects = g_list_remove (data->objects, node);
|
||||
g_object_unref (node);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_connect_client (PinosDaemon1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GVariant *arg_properties,
|
||||
gpointer user_data)
|
||||
handle_create_node (PinosDaemon1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar *arg_factory_name,
|
||||
const gchar *arg_name,
|
||||
GVariant *arg_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosDaemon *daemon = user_data;
|
||||
PinosDaemonPrivate *priv = daemon->priv;
|
||||
PinosClient *client;
|
||||
const gchar *sender, *object_path;
|
||||
PinosNode *node;
|
||||
SenderData *data;
|
||||
const gchar *sender, *object_path;
|
||||
PinosProperties *props;
|
||||
|
||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
|
||||
g_debug ("daemon %p: connect client: %s", daemon, sender);
|
||||
g_debug ("daemon %p: create node: %s", daemon, sender);
|
||||
|
||||
props = pinos_properties_from_variant (arg_properties);
|
||||
client = pinos_client_new (daemon, sender, props);
|
||||
node = pinos_server_node_new (daemon,
|
||||
sender,
|
||||
arg_name,
|
||||
props);
|
||||
pinos_properties_free (props);
|
||||
|
||||
g_signal_connect (client, "disconnect", (GCallback) handle_disconnect_client, daemon);
|
||||
if (node == NULL)
|
||||
goto no_node;
|
||||
|
||||
data = g_hash_table_lookup (priv->senders, sender);
|
||||
if (data == NULL)
|
||||
data = sender_data_new (daemon, sender);
|
||||
|
||||
data->objects = g_list_prepend (data->objects, client);
|
||||
data->objects = g_list_prepend (data->objects, node);
|
||||
|
||||
object_path = pinos_client_get_object_path (client);
|
||||
g_debug ("daemon %p: added client %p with path %s", daemon, client, object_path);
|
||||
g_signal_connect (node,
|
||||
"remove",
|
||||
(GCallback) handle_remove_node,
|
||||
daemon);
|
||||
|
||||
object_path = pinos_server_node_get_object_path (PINOS_SERVER_NODE (node));
|
||||
g_debug ("daemon %p: added node %p with path %s", daemon, node, object_path);
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(o)", object_path));
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
no_node:
|
||||
{
|
||||
g_debug ("daemon %p: could create node named %s from factory %s", daemon, arg_name, arg_factory_name);
|
||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
||||
"org.pinos.Error", "can't create node");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -185,20 +206,9 @@ export_server_object (PinosDaemon *daemon,
|
|||
PinosObjectSkeleton *skel;
|
||||
|
||||
skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_SERVER);
|
||||
{
|
||||
PinosDaemon1 *iface;
|
||||
|
||||
iface = pinos_daemon1_skeleton_new ();
|
||||
g_signal_connect (iface, "handle-connect-client", (GCallback) handle_connect_client, daemon);
|
||||
pinos_daemon1_set_user_name (iface, g_get_user_name ());
|
||||
pinos_daemon1_set_host_name (iface, g_get_host_name ());
|
||||
pinos_daemon1_set_version (iface, PACKAGE_VERSION);
|
||||
pinos_daemon1_set_name (iface, PACKAGE_NAME);
|
||||
pinos_daemon1_set_cookie (iface, g_random_int());
|
||||
pinos_daemon1_set_properties (iface, pinos_properties_to_variant (priv->properties));
|
||||
pinos_object_skeleton_set_daemon1 (skel, iface);
|
||||
g_object_unref (iface);
|
||||
}
|
||||
pinos_object_skeleton_set_daemon1 (skel, priv->iface);
|
||||
|
||||
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (skel));
|
||||
g_object_unref (skel);
|
||||
}
|
||||
|
|
@ -254,6 +264,23 @@ pinos_daemon_new (PinosProperties *properties)
|
|||
return g_object_new (PINOS_TYPE_DAEMON, "properties", properties, NULL);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
pinos_daemon_get_sender (PinosDaemon *daemon)
|
||||
{
|
||||
PinosDaemonPrivate *priv;
|
||||
const gchar *res;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL);
|
||||
priv = daemon->priv;
|
||||
|
||||
if (priv->connection)
|
||||
res = g_dbus_connection_get_unique_name (priv->connection);
|
||||
else
|
||||
res = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_daemon_start:
|
||||
* @daemon: a #PinosDaemon
|
||||
|
|
@ -505,6 +532,23 @@ pinos_daemon_set_property (GObject *_object,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_daemon_constructed (GObject * object)
|
||||
{
|
||||
PinosDaemon *daemon = PINOS_DAEMON_CAST (object);
|
||||
PinosDaemonPrivate *priv = daemon->priv;
|
||||
|
||||
g_debug ("daemon %p: constructed", object);
|
||||
pinos_daemon1_set_user_name (priv->iface, g_get_user_name ());
|
||||
pinos_daemon1_set_host_name (priv->iface, g_get_host_name ());
|
||||
pinos_daemon1_set_version (priv->iface, PACKAGE_VERSION);
|
||||
pinos_daemon1_set_name (priv->iface, PACKAGE_NAME);
|
||||
pinos_daemon1_set_cookie (priv->iface, g_random_int());
|
||||
pinos_daemon1_set_properties (priv->iface, pinos_properties_to_variant (priv->properties));
|
||||
|
||||
G_OBJECT_CLASS (pinos_daemon_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_daemon_dispose (GObject * object)
|
||||
{
|
||||
|
|
@ -525,6 +569,8 @@ pinos_daemon_finalize (GObject * object)
|
|||
|
||||
g_debug ("daemon %p: finalize", object);
|
||||
g_clear_object (&priv->server_manager);
|
||||
g_clear_object (&priv->iface);
|
||||
g_hash_table_unref (priv->senders);
|
||||
|
||||
G_OBJECT_CLASS (pinos_daemon_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
@ -536,6 +582,7 @@ pinos_daemon_class_init (PinosDaemonClass * klass)
|
|||
|
||||
g_type_class_add_private (klass, sizeof (PinosDaemonPrivate));
|
||||
|
||||
gobject_class->constructed = pinos_daemon_constructed;
|
||||
gobject_class->dispose = pinos_daemon_dispose;
|
||||
gobject_class->finalize = pinos_daemon_finalize;
|
||||
|
||||
|
|
@ -560,6 +607,8 @@ pinos_daemon_init (PinosDaemon * daemon)
|
|||
PinosDaemonPrivate *priv = daemon->priv = PINOS_DAEMON_GET_PRIVATE (daemon);
|
||||
|
||||
g_debug ("daemon %p: new", daemon);
|
||||
priv->iface = pinos_daemon1_skeleton_new ();
|
||||
g_signal_connect (priv->iface, "handle-create-node", (GCallback) handle_create_node, daemon);
|
||||
|
||||
priv->server_manager = g_dbus_object_manager_server_new (PINOS_DBUS_OBJECT_PREFIX);
|
||||
priv->senders = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ struct _PinosDaemonClass {
|
|||
GType pinos_daemon_get_type (void);
|
||||
|
||||
PinosDaemon * pinos_daemon_new (PinosProperties *properties);
|
||||
const gchar * pinos_daemon_get_sender (PinosDaemon *daemon);
|
||||
|
||||
void pinos_daemon_start (PinosDaemon *daemon);
|
||||
void pinos_daemon_stop (PinosDaemon *daemon);
|
||||
|
|
|
|||
|
|
@ -336,10 +336,13 @@ on_property_notify (GObject *obj,
|
|||
PinosNode *node = user_data;
|
||||
PinosServerNodePrivate *priv = PINOS_SERVER_NODE (node)->priv;
|
||||
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "name")) {
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "sender") == 0) {
|
||||
pinos_node1_set_owner (priv->iface, priv->sender);
|
||||
}
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "name") == 0) {
|
||||
pinos_node1_set_name (priv->iface, pinos_node_get_name (node));
|
||||
}
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "properties")) {
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "properties") == 0) {
|
||||
PinosProperties *props = pinos_node_get_properties (node);
|
||||
pinos_node1_set_properties (priv->iface, props ? pinos_properties_to_variant (props) : NULL);
|
||||
}
|
||||
|
|
@ -349,12 +352,18 @@ static void
|
|||
pinos_server_node_constructed (GObject * obj)
|
||||
{
|
||||
PinosServerNode *node = PINOS_SERVER_NODE (obj);
|
||||
PinosServerNodePrivate *priv = node->priv;
|
||||
|
||||
g_debug ("server-node %p: constructed", node);
|
||||
|
||||
g_signal_connect (node, "notify", (GCallback) on_property_notify, node);
|
||||
G_OBJECT_CLASS (pinos_server_node_parent_class)->constructed (obj);
|
||||
|
||||
if (priv->sender == NULL) {
|
||||
priv->sender = g_strdup (pinos_daemon_get_sender (priv->daemon));
|
||||
pinos_node1_set_owner (priv->iface, priv->sender);
|
||||
}
|
||||
|
||||
node_register_object (node);
|
||||
}
|
||||
|
||||
|
|
@ -378,6 +387,7 @@ pinos_server_node_finalize (GObject * obj)
|
|||
g_debug ("server-node %p: finalize", node);
|
||||
g_clear_object (&priv->daemon);
|
||||
g_clear_object (&priv->iface);
|
||||
g_free (priv->sender);
|
||||
|
||||
G_OBJECT_CLASS (pinos_server_node_parent_class)->finalize (obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,8 +164,6 @@ on_property_notify (GObject *obj,
|
|||
PinosPort *port = PINOS_PORT (obj);
|
||||
PinosServerPortPrivate *priv = PINOS_SERVER_PORT (port)->priv;
|
||||
|
||||
g_debug ("port %p: update %s", port, pspec ? g_param_spec_get_name (pspec) : "NULL");
|
||||
|
||||
if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "node") == 0) {
|
||||
PinosServerNode *node = PINOS_SERVER_NODE (pinos_port_get_node (port));
|
||||
pinos_port1_set_node (priv->iface, pinos_server_node_get_object_path (node));
|
||||
|
|
|
|||
|
|
@ -123,19 +123,6 @@ dump_daemon_info (PinosContext *c, const PinosDaemonInfo *info, gpointer user_da
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_client_info (PinosContext *c, const PinosClientInfo *info, gpointer user_data)
|
||||
{
|
||||
DumpData *data = user_data;
|
||||
|
||||
g_print ("\tid: %p\n", info->id);
|
||||
g_print ("\tclient-path: \"%s\"\n", info->client_path);
|
||||
if (data->print_all) {
|
||||
g_print ("\tsender: \"%s\"\n", info->sender);
|
||||
print_properties (info->properties, MARK_CHANGE (0));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_node_info (PinosContext *c, const PinosNodeInfo *info, gpointer user_data)
|
||||
{
|
||||
|
|
@ -144,6 +131,7 @@ dump_node_info (PinosContext *c, const PinosNodeInfo *info, gpointer user_data)
|
|||
g_print ("\tid: %p\n", info->id);
|
||||
g_print ("\tnode-path: \"%s\"\n", info->node_path);
|
||||
if (data->print_all) {
|
||||
g_print ("%c\towner: \"%s\"\n", MARK_CHANGE (0), info->owner);
|
||||
g_print ("%c\tname: \"%s\"\n", MARK_CHANGE (0), info->name);
|
||||
print_properties (info->properties, MARK_CHANGE (1));
|
||||
g_print ("%c\tstate: \"%s\"\n", MARK_CHANGE (2), pinos_node_state_as_string (info->state));
|
||||
|
|
@ -194,15 +182,6 @@ dump_object (PinosContext *context, gpointer id, PinosSubscriptionFlags flags,
|
|||
info_ready,
|
||||
data);
|
||||
}
|
||||
else if (flags & PINOS_SUBSCRIPTION_FLAG_CLIENT) {
|
||||
pinos_context_get_client_info_by_id (context,
|
||||
id,
|
||||
PINOS_CLIENT_INFO_FLAGS_NONE,
|
||||
dump_client_info,
|
||||
NULL,
|
||||
info_ready,
|
||||
data);
|
||||
}
|
||||
else if (flags & PINOS_SUBSCRIPTION_FLAG_NODE) {
|
||||
pinos_context_get_node_info_by_id (context,
|
||||
id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue