diff --git a/doc/design.txt b/doc/design.txt index 56605a4ad..a5ea69922 100644 --- a/doc/design.txt +++ b/doc/design.txt @@ -35,8 +35,8 @@ Node1: a processing node, this can be a source, sink or transform /org/pinos/node* Port1: a port on a Node1, ports can be input or output ports /org/pinos/node*/port* -Channel1: a connection of a client on a port - /org/pinos/client*/channel* +Link1: a link between 2 ports + /org/pinos/link* DBus protocol diff --git a/pinos/Makefile.am b/pinos/Makefile.am index 4f989b17d..1201c86a9 100644 --- a/pinos/Makefile.am +++ b/pinos/Makefile.am @@ -170,6 +170,10 @@ pinosinclude_HEADERS = \ client/introspect.h \ client/mainloop.h \ client/properties.h \ + client/node.h \ + client/port.h \ + client/client-node.h \ + client/client-port.h \ client/stream.h \ client/subscribe.h @@ -184,6 +188,10 @@ libpinos_@PINOS_MAJORMINOR@_la_SOURCES = \ client/introspect.h client/introspect.c \ client/mainloop.h client/mainloop.c \ client/properties.h client/properties.c \ + client/node.h client/node.c \ + client/port.h client/port.c \ + client/client-node.h client/client-node.c \ + client/client-port.h client/client-port.c \ client/stream.h client/stream.c \ client/pinos.c client/pinos.h \ client/fdmanager.c client/fdmanager.h \ @@ -205,10 +213,9 @@ lib_LTLIBRARIES += libpinoscore-@PINOS_MAJORMINOR@.la libpinoscore_@PINOS_MAJORMINOR@_la_SOURCES = \ server/client.c server/client.h \ server/daemon.c server/daemon.h \ - server/node.c server/node.h \ - server/port.c server/port.h \ + server/server-node.c server/server-node.h \ + server/server-port.c server/server-port.h \ server/upload-node.c server/upload-node.h \ - server/channel.c server/channel.h \ modules/gst/gst-manager.c modules/gst/gst-manager.h \ modules/gst/gst-source.c modules/gst/gst-source.h \ modules/gst/gst-sink.c modules/gst/gst-sink.h \ diff --git a/pinos/client/context.c b/pinos/client/context.c index 1d7c22864..316b1dfd9 100644 --- a/pinos/client/context.c +++ b/pinos/client/context.c @@ -22,6 +22,7 @@ #include "pinos/client/context.h" #include "pinos/client/enumtypes.h" #include "pinos/client/subscribe.h" +#include "pinos/client/client-node.h" #include "pinos/client/private.h" @@ -150,7 +151,6 @@ pinos_context_finalize (GObject * object) g_list_free (priv->nodes); g_list_free (priv->ports); g_list_free (priv->clients); - g_list_free (priv->channels); g_clear_object (&priv->subscribe); g_clear_error (&priv->error); @@ -501,13 +501,6 @@ subscription_cb (PinosSubscribe *subscribe, else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) priv->ports = g_list_remove (priv->ports, object); break; - - case PINOS_SUBSCRIPTION_FLAG_CHANNEL: - if (event == PINOS_SUBSCRIPTION_EVENT_NEW) - priv->channels = g_list_prepend (priv->channels, object); - else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) - priv->channels = g_list_remove (priv->channels, object); - break; } if (flags & priv->subscription_mask) @@ -761,3 +754,171 @@ pinos_context_get_error (PinosContext *context) return priv->error; } + +typedef struct { + gchar *name; + PinosProperties *properties; +} CreateNodeData; + +static void +create_node_data_free (CreateNodeData *data) +{ + g_free (data->name); + if (data->properties) + pinos_properties_free (data->properties); + g_slice_free (CreateNodeData, data); +} + +static void +on_node_proxy (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GTask *task = user_data; + PinosContext *context = g_task_get_source_object (task); + GError *error = NULL; + GDBusProxy *proxy; + PinosNode *node; + + proxy = pinos_subscribe_get_proxy_finish (context->priv->subscribe, + res, + &error); + if (proxy == NULL) + goto node_failed; + + node = g_object_new (PINOS_TYPE_CLIENT_NODE, + "context", context, + "proxy", proxy, + NULL); + + g_task_return_pointer (task, node, (GDestroyNotify) g_object_unref); + + return; + +node_failed: + { + g_warning ("failed to get node proxy: %s", error->message); + g_task_return_error (task, error); + return; + } +} + + +static void +on_node_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GTask *task = user_data; + PinosContext *context = g_task_get_source_object (task); + GVariant *ret; + GError *error = NULL; + const gchar *node_path; + + g_assert (context->priv->client == G_DBUS_PROXY (source_object)); + + ret = g_dbus_proxy_call_finish (context->priv->client, res, &error); + if (ret == NULL) + goto create_failed; + + g_variant_get (ret, "(&o)", &node_path); + + pinos_subscribe_get_proxy (context->priv->subscribe, + PINOS_DBUS_SERVICE, + node_path, + "org.pinos.Node1", + NULL, + on_node_proxy, + task); + g_variant_unref (ret); + + return; + + /* ERRORS */ +create_failed: + { + g_warning ("failed to create node: %s", error->message); + g_task_return_error (task, error); + return; + } +} + + +static gboolean +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, + "CreateNode", + g_variant_new ("(s@a{sv})", + "client-node", + pinos_properties_to_variant (data->properties)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, /* GCancellable *cancellable */ + on_node_created, + task); + return FALSE; +} + +/** + * pinos_context_create_node: + * @context: a #PinosContext + * @name: the name of the Node + * @properties: properties of the node + * @cancelable: a #GCancellable + * @callback: a #GAsyncReadyCallback + * @user_data: user data. + * + * Asynchronously create a new node in @context. + */ +void +pinos_context_create_node (PinosContext *context, + const gchar *name, + PinosProperties *properties, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + CreateNodeData *data; + + g_return_if_fail (PINOS_IS_CONTEXT (context)); + + task = g_task_new (context, + cancellable, + callback, + user_data); + + data = g_slice_new (CreateNodeData); + data->name = g_strdup (name); + data->properties = properties ? pinos_properties_copy (properties) : NULL; + + g_task_set_task_data (task, data, (GDestroyNotify) create_node_data_free); + + g_main_context_invoke (context->priv->context, + (GSourceFunc) do_create_node, + task); +} + +/** + * pinos_context_create_node_finish: + * @context: a #PinosContext + * @res: a #GAsyncResult + * @error: a #GError or %NULL + * + * Get the newly created #PinosNode. This function should be called in the callback + * of pinos_context_create_node() to get the result or error. + * + * Returns: a new #PinosNode. If %NULL is returned, @error will + * be set. + */ +PinosNode * +pinos_context_create_node_finish (PinosContext *context, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (res), error); +} diff --git a/pinos/client/context.h b/pinos/client/context.h index ec3a6ee61..85c8f88b2 100644 --- a/pinos/client/context.h +++ b/pinos/client/context.h @@ -22,11 +22,17 @@ #include -#include -#include G_BEGIN_DECLS +typedef struct _PinosContext PinosContext; +typedef struct _PinosContextClass PinosContextClass; +typedef struct _PinosContextPrivate PinosContextPrivate; + +#include +#include +#include + #define PINOS_TYPE_CONTEXT (pinos_context_get_type ()) #define PINOS_IS_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_CONTEXT)) #define PINOS_IS_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_CONTEXT)) @@ -36,10 +42,6 @@ G_BEGIN_DECLS #define PINOS_CONTEXT_CAST(obj) ((PinosContext*)(obj)) #define PINOS_CONTEXT_CLASS_CAST(klass) ((PinosContextClass*)(klass)) -typedef struct _PinosContext PinosContext; -typedef struct _PinosContextClass PinosContextClass; -typedef struct _PinosContextPrivate PinosContextPrivate; - /** * PinosContextFlags: * @PINOS_CONTEXT_FLAGS_NONE: no flags @@ -106,6 +108,16 @@ PinosContext * pinos_context_new (GMainContext *ctx, gboolean pinos_context_connect (PinosContext *context, PinosContextFlags flags); gboolean pinos_context_disconnect (PinosContext *context); +void pinos_context_create_node (PinosContext *context, + const gchar *name, + PinosProperties *properties, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +PinosNode * pinos_context_create_node_finish (PinosContext *context, + GAsyncResult *res, + GError **error); + PinosContextState pinos_context_get_state (PinosContext *context); const GError * pinos_context_get_error (PinosContext *context); diff --git a/pinos/client/introspect.c b/pinos/client/introspect.c index 31f68fcbe..3adee04d1 100644 --- a/pinos/client/introspect.c +++ b/pinos/client/introspect.c @@ -532,74 +532,63 @@ pinos_context_get_port_info_by_id (PinosContext *context, } /** - * pinos_channel_state_as_string: - * @state: a #PinosChannelState + * pinos_port_state_as_string: + * @state: a #PinosPortState * * Return the string representation of @state. * * Returns: the string representation of @state. */ const gchar * -pinos_channel_state_as_string (PinosChannelState state) +pinos_port_state_as_string (PinosPortState state) { GEnumValue *val; - val = g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (PINOS_TYPE_CHANNEL_STATE)), + val = g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (PINOS_TYPE_PORT_STATE)), state); return val == NULL ? "invalid-state" : val->value_nick; } static void -channel_fill_info (PinosChannelInfo *info, GDBusProxy *proxy) +connection_fill_info (PinosConnectionInfo *info, GDBusProxy *proxy) { GHashTable *changed = g_object_get_data (G_OBJECT (proxy), "pinos-changed-properties"); info->id = proxy; - info->channel_path = g_dbus_proxy_get_object_path (proxy); - SET_UINT32 ("Direction", direction, 2, PINOS_DIRECTION_INVALID); - SET_STRING ("Client", client_path, 0); + info->connection_path = g_dbus_proxy_get_object_path (proxy); info->change_mask = 0; - SET_STRING ("Port", port_path, 0); - SET_PROPERTIES ("Properties", properties, 1); - SET_UINT32 ("State", state, 2, PINOS_CHANNEL_STATE_ERROR); - SET_BYTES ("PossibleFormats", possible_formats, 3); - SET_BYTES ("Format", format, 4); + SET_STRING ("SourcePort", source_port_path, 0); + SET_STRING ("DestinationPort", destination_port_path, 1); if (changed) g_hash_table_remove_all (changed); } static void -channel_clear_info (PinosChannelInfo *info) +connection_clear_info (PinosConnectionInfo *info) { - if (info->possible_formats) - g_bytes_unref (info->possible_formats); - if (info->format) - g_bytes_unref (info->format); - if (info->properties) - pinos_properties_free (info->properties); } /** - * pinos_context_list_channel_info: + * pinos_context_list_connection_info: * @context: a connected #PinosContext - * @flags: extra #PinosChannelInfoFlags - * @cb: a #PinosChannelInfoCallback + * @flags: extra #PinosConnectionInfoFlags + * @cb: a #PinosConnectionInfoCallback * @cancelable: a #GCancellable * @callback: a #GAsyncReadyCallback to call when the operation is finished * @user_data: user data passed to @cb * - * Call @cb for each channel. + * Call @cb for each connection. */ void -pinos_context_list_channel_info (PinosContext *context, - PinosChannelInfoFlags flags, - PinosChannelInfoCallback cb, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +pinos_context_list_connection_info (PinosContext *context, + PinosConnectionInfoFlags flags, + PinosConnectionInfoCallback cb, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { PinosContextPrivate *priv; GList *walk; @@ -612,13 +601,13 @@ pinos_context_list_channel_info (PinosContext *context, priv = context->priv; - for (walk = priv->channels; walk; walk = g_list_next (walk)) { + for (walk = priv->connections; walk; walk = g_list_next (walk)) { GDBusProxy *proxy = walk->data; - PinosChannelInfo info; + PinosConnectionInfo info; - channel_fill_info (&info, proxy); + connection_fill_info (&info, proxy); cb (context, &info, user_data); - channel_clear_info (&info); + connection_clear_info (&info); } g_task_return_boolean (task, TRUE); @@ -626,27 +615,27 @@ pinos_context_list_channel_info (PinosContext *context, } /** - * pinos_context_get_channel_info_by_id: + * pinos_context_get_connection_info_by_id: * @context: a connected #PinosContext - * @id: a channel id - * @flags: extra #PinosChannelInfoFlags - * @cb: a #PinosChannelInfoCallback + * @id: a connection id + * @flags: extra #PinosConnectionInfoFlags + * @cb: a #PinosConnectionInfoCallback * @cancelable: a #GCancellable * @callback: a #GAsyncReadyCallback to call when the operation is finished * @user_data: user data passed to @cb * - * Call @cb for the channel with @id. + * Call @cb for the connection with @id. */ void -pinos_context_get_channel_info_by_id (PinosContext *context, - gpointer id, - PinosChannelInfoFlags flags, - PinosChannelInfoCallback cb, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +pinos_context_get_connection_info_by_id (PinosContext *context, + gpointer id, + PinosConnectionInfoFlags flags, + PinosConnectionInfoCallback cb, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { - PinosChannelInfo info; + PinosConnectionInfo info; GDBusProxy *proxy; GTask *task; @@ -658,9 +647,9 @@ pinos_context_get_channel_info_by_id (PinosContext *context, proxy = G_DBUS_PROXY (id); - channel_fill_info (&info, proxy); + connection_fill_info (&info, proxy); cb (context, &info, user_data); - channel_clear_info (&info); + connection_clear_info (&info); g_task_return_boolean (task, TRUE); g_object_unref (task); diff --git a/pinos/client/introspect.h b/pinos/client/introspect.h index 1fdf48a69..654126cb3 100644 --- a/pinos/client/introspect.h +++ b/pinos/client/introspect.h @@ -23,11 +23,68 @@ #include #include +G_BEGIN_DECLS + +/** + * PinosNodeState: + * @PINOS_NODE_STATE_ERROR: the node is in error + * @PINOS_NODE_STATE_SUSPENDED: the node is suspended, the device might + * be closed + * @PINOS_NODE_STATE_INITIALIZING: the node is initializing, the device is + * being opened and the capabilities are queried + * @PINOS_NODE_STATE_IDLE: the node is running but there is no active + * port + * @PINOS_NODE_STATE_RUNNING: the node is running + * + * The different node states + */ +typedef enum { + PINOS_NODE_STATE_ERROR = -1, + PINOS_NODE_STATE_SUSPENDED = 0, + PINOS_NODE_STATE_INITIALIZING = 1, + PINOS_NODE_STATE_IDLE = 2, + PINOS_NODE_STATE_RUNNING = 3, +} PinosNodeState; + +const gchar * pinos_node_state_as_string (PinosNodeState state); + +/** + * PinosDirection: + * @PINOS_DIRECTION_INVALID: invalid direction + * @PINOS_DIRECTION_INPUT: an input port + * @PINOS_DIRECTION_OUTPUT: an output port + * + * The direction of a port + */ +typedef enum { + PINOS_DIRECTION_INVALID = -1, + PINOS_DIRECTION_INPUT = 0, + PINOS_DIRECTION_OUTPUT = 1 +} PinosDirection; + +const gchar * pinos_direction_as_string (PinosDirection direction); + +/** + * PinosPortState: + * @PINOS_PORT_STATE_ERROR: the port is in error + * @PINOS_PORT_STATE_STOPPED: the port is stopped + * @PINOS_PORT_STATE_STARTING: the port is starting + * @PINOS_PORT_STATE_STREAMING: the port is streaming + * + * The different port states + */ +typedef enum { + PINOS_PORT_STATE_ERROR = -1, + PINOS_PORT_STATE_STOPPED = 0, + PINOS_PORT_STATE_STARTING = 1, + PINOS_PORT_STATE_STREAMING = 2, +} PinosPortState; + +const gchar * pinos_port_state_as_string (PinosPortState state); + #include #include -G_BEGIN_DECLS - gboolean pinos_context_info_finish (GObject *object, GAsyncResult *res, GError **error); @@ -143,29 +200,6 @@ void pinos_context_get_client_info_by_id (PinosContext *context, GAsyncReadyCallback callback, gpointer user_data); -/** - * PinosNodeState: - * @PINOS_NODE_STATE_ERROR: the node is in error - * @PINOS_NODE_STATE_SUSPENDED: the node is suspended, the device might - * be closed - * @PINOS_NODE_STATE_INITIALIZING: the node is initializing, the device is - * being opened and the capabilities are queried - * @PINOS_NODE_STATE_IDLE: the node is running but there is no active - * channel - * @PINOS_NODE_STATE_RUNNING: the node is running - * - * The different node states - */ -typedef enum { - PINOS_NODE_STATE_ERROR = -1, - PINOS_NODE_STATE_SUSPENDED = 0, - PINOS_NODE_STATE_INITIALIZING = 1, - PINOS_NODE_STATE_IDLE = 2, - PINOS_NODE_STATE_RUNNING = 3, -} PinosNodeState; - -const gchar * pinos_node_state_as_string (PinosNodeState state); - /** * PinosNodeInfo: * @id: generic id of the node @@ -223,21 +257,6 @@ void pinos_context_get_node_info_by_id (PinosContext *context, GAsyncReadyCallback callback, gpointer user_data); -/** - * PinosDirection: - * @PINOS_DIRECTION_INVALID: invalid direction - * @PINOS_DIRECTION_INPUT: an input port/channel - * @PINOS_DIRECTION_OUTPUT: an output port/channel - * - * The direction of a port or channel - */ -typedef enum { - PINOS_DIRECTION_INVALID = -1, - PINOS_DIRECTION_INPUT = 0, - PINOS_DIRECTION_OUTPUT = 1 -} PinosDirection; - -const gchar * pinos_direction_as_string (PinosDirection direction); /** * PinosPortInfo: @@ -302,92 +321,60 @@ void pinos_context_get_port_info_by_id (PinosContext *context, GAsyncReadyCallback callback, gpointer user_data); /** - * PinosChannelState: - * @PINOS_CHANNEL_STATE_ERROR: the channel is in error - * @PINOS_CHANNEL_STATE_STOPPED: the channel is stopped - * @PINOS_CHANNEL_STATE_STARTING: the channel is starting - * @PINOS_CHANNEL_STATE_STREAMING: the channel is streaming - * - * The different channel states - */ -typedef enum { - PINOS_CHANNEL_STATE_ERROR = -1, - PINOS_CHANNEL_STATE_STOPPED = 0, - PINOS_CHANNEL_STATE_STARTING = 1, - PINOS_CHANNEL_STATE_STREAMING = 2, -} PinosChannelState; - -const gchar * pinos_channel_state_as_string (PinosChannelState state); - -/** - * PinosChannelInfo: - * @id: generic id of the channel_ - * @channel_path: the unique path of the channel - * @direction: the channel direction - * @client_path: the owner client + * PinosConnectionInfo: + * @id: generic id of the connection + * @connection_path: the unique path of the connection * @change_mask: bitfield of changed fields since last call - * @port_path: the owner port - * @properties: the properties of the channel - * @state: the state - * @possible_formats: the possible formats - * @format: when streaming, the current format + * @source_port_path: the source port + * @destination_port_path: the destination port * - * The channel information. Extra information can be added in later + * The connection information. Extra information can be added in later * versions. */ typedef struct { gpointer id; - const char *channel_path; - PinosDirection direction; - const char *client_path; + const char *connection_path; guint64 change_mask; - const char *port_path; - PinosProperties *properties; - PinosChannelState state; - GBytes *possible_formats; - GBytes *format; -} PinosChannelInfo; + const char *source_port_path; + const char *destination_port_path; +} PinosConnectionInfo; /** - * PinosChannelInfoFlags: - * @PINOS_CHANNEL_INFO_FLAGS_NONE: no flags - * @PINOS_CHANNEL_INFO_FLAGS_NO_INPUT: don't list input channels - * @PINOS_CHANNEL_INFO_FLAGS_NO_OUTPUT: don't list output channels + * PinosConnectionInfoFlags: + * @PINOS_CONNECTION_INFO_FLAGS_NONE: no flags * - * Extra flags to pass to pinos_context_list_channel_info() and - * pinos_context_get_channel_info_by_id(). + * Extra flags to pass to pinos_context_list_connection_info() and + * pinos_context_get_connection_info_by_id(). */ typedef enum { - PINOS_CHANNEL_INFO_FLAGS_NONE = 0, - PINOS_CHANNEL_INFO_FLAGS_NO_INPUT = (1 << 0), - PINOS_CHANNEL_INFO_FLAGS_NO_OUTPUT = (1 << 1), -} PinosChannelInfoFlags; + PINOS_CONNECTION_INFO_FLAGS_NONE = 0, +} PinosConnectionInfoFlags; /** - * PinosChannelInfoCallback: + * PinosConnectionInfoCallback: * @c: a #PinosContext - * @info: a #PinosChannelInfo + * @info: a #PinosConnectionInfo * @user_data: user data * - * Callback with information about the Pinos channel in @info. + * Callback with information about the Pinos connection in @info. */ -typedef void (*PinosChannelInfoCallback) (PinosContext *c, - const PinosChannelInfo *info, - gpointer user_data); +typedef void (*PinosConnectionInfoCallback) (PinosContext *c, + const PinosConnectionInfo *info, + gpointer user_data); -void pinos_context_list_channel_info (PinosContext *context, - PinosChannelInfoFlags flags, - PinosChannelInfoCallback cb, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -void pinos_context_get_channel_info_by_id (PinosContext *context, - gpointer id, - PinosChannelInfoFlags flags, - PinosChannelInfoCallback cb, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); +void pinos_context_list_connection_info (PinosContext *context, + PinosConnectionInfoFlags flags, + PinosConnectionInfoCallback cb, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +void pinos_context_get_connection_info_by_id (PinosContext *context, + gpointer id, + PinosConnectionInfoFlags flags, + PinosConnectionInfoCallback cb, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); G_END_DECLS #endif /* __PINOS_INTROSPECT_H__ */ diff --git a/pinos/client/private.h b/pinos/client/private.h index 78e83432e..ce9df41b1 100644 --- a/pinos/client/private.h +++ b/pinos/client/private.h @@ -42,7 +42,7 @@ struct _PinosContextPrivate GList *clients; GList *nodes; GList *ports; - GList *channels; + GList *connections; }; void pinos_subscribe_get_proxy (PinosSubscribe *subscribe, diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 3935925ce..3de28d4ec 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -49,7 +49,8 @@ struct _PinosStreamPrivate GBytes *format; - GDBusProxy *channel; + PinosNode *node; + PinosPort *port; gboolean disconnecting; PinosStreamMode mode; @@ -197,14 +198,14 @@ subscription_cb (PinosSubscribe *subscribe, PinosStreamPrivate *priv = stream->priv; switch (flags) { - case PINOS_SUBSCRIPTION_FLAG_CHANNEL: + case PINOS_SUBSCRIPTION_FLAG_NODE: if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) { - if (object == priv->channel && !priv->disconnecting) { + if (object == priv->node && !priv->disconnecting) { stream_set_state (stream, PINOS_STREAM_STATE_ERROR, g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, - "Channel disappeared")); + "Node disappeared")); } } break; @@ -237,7 +238,8 @@ pinos_stream_finalize (GObject * object) g_debug ("free stream %p", stream); g_clear_object (&priv->socket); - g_clear_object (&priv->channel); + g_clear_object (&priv->node); + g_clear_object (&priv->port); if (priv->possible_formats) g_bytes_unref (priv->possible_formats); @@ -493,64 +495,31 @@ pinos_stream_get_error (PinosStream *stream) } static void -on_channel_proxy (GObject *source_object, - GAsyncResult *res, - gpointer user_data) +on_port_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { PinosStream *stream = user_data; PinosStreamPrivate *priv = stream->priv; - PinosContext *context = priv->context; - GVariant *v; - gchar *str; GError *error = NULL; - priv->channel = pinos_subscribe_get_proxy_finish (context->priv->subscribe, - res, - &error); - if (priv->channel == NULL) - goto channel_failed; + g_assert (priv->node == PINOS_NODE (source_object)); - /* get the port we are connected to */ - v = g_dbus_proxy_get_cached_property (priv->channel, "Port"); - if (v) { - gsize len; - str = g_variant_dup_string (v, &len); - g_variant_unref (v); - - g_free (priv->path); - priv->path = str; - } - - v = g_dbus_proxy_get_cached_property (priv->channel, "PossibleFormats"); - if (v) { - gsize len; - str = g_variant_dup_string (v, &len); - g_variant_unref (v); - - if (priv->possible_formats) - g_bytes_unref (priv->possible_formats); - priv->possible_formats = g_bytes_new_take (str, len + 1); - - g_object_notify (G_OBJECT (stream), "possible-formats"); - } - v = g_dbus_proxy_get_cached_property (priv->channel, "Properties"); - if (v) { - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = pinos_properties_from_variant (v); - g_variant_unref (v); - - g_object_notify (G_OBJECT (stream), "properties"); - } + priv->port = pinos_node_create_port_finish (priv->node, + res, + &error); + if (priv->port == NULL) + goto create_failed; stream_set_state (stream, PINOS_STREAM_STATE_READY, NULL); g_object_unref (stream); return; -channel_failed: + /* ERRORS */ +create_failed: { - g_warning ("failed to get channel proxy: %s", error->message); + g_warning ("failed to create port: %s", error->message); stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error); g_object_unref (stream); return; @@ -558,40 +527,33 @@ channel_failed: } static void -on_channel_created (GObject *source_object, - GAsyncResult *res, - gpointer user_data) +on_node_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { PinosStream *stream = user_data; PinosStreamPrivate *priv = stream->priv; PinosContext *context = priv->context; - GVariant *ret; GError *error = NULL; - const gchar *channel_path; - g_assert (context->priv->client == G_DBUS_PROXY (source_object)); - - ret = g_dbus_proxy_call_finish (context->priv->client, res, &error); - if (ret == NULL) + priv->node = pinos_context_create_node_finish (context, res, &error); + if (priv->node == NULL) goto create_failed; - g_variant_get (ret, "(&o)", &channel_path); - - pinos_subscribe_get_proxy (context->priv->subscribe, - PINOS_DBUS_SERVICE, - channel_path, - "org.pinos.Channel1", - NULL, - on_channel_proxy, + pinos_node_create_port (priv->node, + priv->direction, + "client-port", + priv->possible_formats, + priv->properties, + NULL, /* GCancellable *cancellable */ + on_port_created, stream); - g_variant_unref (ret); - return; /* ERRORS */ create_failed: { - g_warning ("failed to get connect capture: %s", error->message); + g_warning ("failed to create node: %s", error->message); stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error); g_object_unref (stream); return; @@ -604,19 +566,12 @@ do_connect (PinosStream *stream) PinosStreamPrivate *priv = stream->priv; PinosContext *context = priv->context; - g_dbus_proxy_call (context->priv->client, - "CreateChannel", - g_variant_new ("(uss@a{sv})", - priv->direction, - (priv->path ? priv->path : ""), - g_bytes_get_data (priv->possible_formats, NULL), - pinos_properties_to_variant (priv->properties)), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* GCancellable *cancellable */ - on_channel_created, - stream); - + pinos_context_create_node (context, + "client-node", + priv->properties, + NULL, /* GCancellable *cancellable */ + on_node_created, + stream); return FALSE; } @@ -670,6 +625,7 @@ pinos_stream_connect (PinosStream *stream, static gboolean do_connect_provide (PinosStream *stream) { +#if 0 PinosStreamPrivate *priv = stream->priv; PinosContext *context = priv->context; @@ -683,6 +639,7 @@ do_connect_provide (PinosStream *stream) NULL, /* GCancellable *cancellable */ on_channel_created, stream); +#endif return FALSE; } @@ -726,39 +683,88 @@ pinos_stream_connect_provide (PinosStream *stream, return TRUE; } -static void -on_channel_removed (GObject *source_object, - GAsyncResult *res, - gpointer user_data) +static gboolean +do_start (PinosStream *stream) { - PinosStream *stream = user_data; - PinosStreamPrivate *priv = stream->priv; - GVariant *ret; - GError *error = NULL; - - g_assert (priv->channel == G_DBUS_PROXY (source_object)); - - priv->disconnecting = FALSE; - g_clear_object (&priv->channel); - - ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); - if (ret == NULL) - goto proxy_failed; - - g_variant_unref (ret); - - stream_set_state (stream, PINOS_STREAM_STATE_UNCONNECTED, NULL); + stream_set_state (stream, PINOS_STREAM_STATE_STREAMING, NULL); g_object_unref (stream); - return; - /* ERRORS */ -proxy_failed: - { - g_warning ("failed to disconnect: %s", error->message); - stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error); - g_object_unref (stream); - return; - } + return FALSE; +} + +/** + * pinos_stream_start: + * @stream: a #PinosStream + * @format: (transfer full): a #GBytes with format + * @mode: a #PinosStreamMode + * + * Start capturing from @stream in @format. + * + * When @mode is #PINOS_STREAM_MODE_SOCKET, you should connect to the notify::socket + * signal to obtain a readable socket with metadata and data. + * + * When @mode is #PINOS_STREAM_MODE_BUFFER, you should connect to the new-buffer + * signal and use pinos_stream_capture_buffer() to get the latest metadata and + * data. + * + * Returns: %TRUE on success. + */ +gboolean +pinos_stream_start (PinosStream *stream, + GBytes *format, + PinosStreamMode mode) +{ + PinosStreamPrivate *priv; + + g_return_val_if_fail (PINOS_IS_STREAM (stream), FALSE); + + priv = stream->priv; + g_return_val_if_fail (priv->state == PINOS_STREAM_STATE_READY, FALSE); + + priv->mode = mode; + priv->format = format; + + stream_set_state (stream, PINOS_STREAM_STATE_STARTING, NULL); + + g_main_context_invoke (priv->context->priv->context, + (GSourceFunc) do_start, + g_object_ref (stream)); + + return TRUE; +} + +static gboolean +do_stop (PinosStream *stream) +{ + stream_set_state (stream, PINOS_STREAM_STATE_READY, NULL); + g_object_unref (stream); + + return FALSE; +} + +/** + * pinos_stream_stop: + * @stream: a #PinosStream + * + * Stop capturing from @stream. + * + * Returns: %TRUE on success. + */ +gboolean +pinos_stream_stop (PinosStream *stream) +{ + PinosStreamPrivate *priv; + + g_return_val_if_fail (PINOS_IS_STREAM (stream), FALSE); + + priv = stream->priv; + g_return_val_if_fail (priv->state == PINOS_STREAM_STATE_STREAMING, FALSE); + + g_main_context_invoke (priv->context->priv->context, + (GSourceFunc) do_stop, + g_object_ref (stream)); + + return TRUE; } static gboolean @@ -766,14 +772,7 @@ do_disconnect (PinosStream *stream) { PinosStreamPrivate *priv = stream->priv; - g_dbus_proxy_call (priv->channel, - "Remove", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* GCancellable *cancellable */ - on_channel_removed, - stream); + pinos_node_remove (priv->node); return FALSE; } @@ -795,7 +794,7 @@ pinos_stream_disconnect (PinosStream *stream) g_return_val_if_fail (PINOS_IS_STREAM (stream), FALSE); priv = stream->priv; g_return_val_if_fail (priv->state >= PINOS_STREAM_STATE_READY, FALSE); - g_return_val_if_fail (priv->channel != NULL, FALSE); + g_return_val_if_fail (priv->node != NULL, FALSE); context = priv->context; g_return_val_if_fail (pinos_context_get_state (context) >= PINOS_CONTEXT_STATE_READY, FALSE); g_return_val_if_fail (!priv->disconnecting, FALSE); @@ -976,212 +975,6 @@ unhandle_socket (PinosStream *stream) } } -static void -on_stream_started (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - PinosStream *stream = user_data; - PinosStreamPrivate *priv = stream->priv; - GUnixFDList *out_fd_list; - gint fd_idx, fd; - gchar *format; - GError *error = NULL; - GVariant *result, *properties; - - result = g_dbus_proxy_call_with_unix_fd_list_finish (priv->channel, - &out_fd_list, - res, - &error); - if (result == NULL) - goto start_failed; - - g_variant_get (result, - "(hs@a{sv})", - &fd_idx, - &format, - &properties); - - g_variant_unref (result); - - if (priv->format) - g_bytes_unref (priv->format); - priv->format = g_bytes_new_take (format, strlen (format) + 1); - g_object_notify (G_OBJECT (stream), "format"); - - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = pinos_properties_from_variant (properties); - g_variant_unref (properties); - - g_object_notify (G_OBJECT (stream), "properties"); - - if ((fd = g_unix_fd_list_get (out_fd_list, fd_idx, &error)) < 0) - goto fd_failed; - - g_object_unref (out_fd_list); - - handle_socket (stream, fd); - - stream_set_state (stream, PINOS_STREAM_STATE_STREAMING, NULL); - g_object_unref (stream); - - return; - - /* ERRORS */ -start_failed: - { - g_warning ("failed to start: %s", error->message); - goto exit_error; - } -fd_failed: - { - g_warning ("failed to get FD: %s", error->message); - g_object_unref (out_fd_list); - goto exit_error; - } -exit_error: - { - stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error); - g_object_unref (stream); - return; - } -} - -static gboolean -do_start (PinosStream *stream) -{ - PinosStreamPrivate *priv = stream->priv; - - g_dbus_proxy_call (priv->channel, - "Start", - g_variant_new ("(s)", g_bytes_get_data (priv->format, NULL)), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* GCancellable *cancellable */ - on_stream_started, - stream); - - return FALSE; -} - -/** - * pinos_stream_start: - * @stream: a #PinosStream - * @format: (transfer full): a #GBytes with format - * @mode: a #PinosStreamMode - * - * Start capturing from @stream in @format. - * - * When @mode is #PINOS_STREAM_MODE_SOCKET, you should connect to the notify::socket - * signal to obtain a readable socket with metadata and data. - * - * When @mode is #PINOS_STREAM_MODE_BUFFER, you should connect to the new-buffer - * signal and use pinos_stream_capture_buffer() to get the latest metadata and - * data. - * - * Returns: %TRUE on success. - */ -gboolean -pinos_stream_start (PinosStream *stream, - GBytes *format, - PinosStreamMode mode) -{ - PinosStreamPrivate *priv; - - g_return_val_if_fail (PINOS_IS_STREAM (stream), FALSE); - - priv = stream->priv; - g_return_val_if_fail (priv->state == PINOS_STREAM_STATE_READY, FALSE); - - priv->mode = mode; - priv->format = format; - - stream_set_state (stream, PINOS_STREAM_STATE_STARTING, NULL); - - g_main_context_invoke (priv->context->priv->context, - (GSourceFunc) do_start, - g_object_ref (stream)); - - return TRUE; -} - -static void -on_stream_stopped (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - PinosStream *stream = user_data; - PinosStreamPrivate *priv = stream->priv; - GVariant *ret; - GError *error = NULL; - - ret = g_dbus_proxy_call_finish (priv->channel, res, &error); - if (ret == NULL) - goto call_failed; - - g_variant_unref (ret); - - unhandle_socket (stream); - g_clear_pointer (&priv->format, g_bytes_unref); - g_object_notify (G_OBJECT (stream), "format"); - - stream_set_state (stream, PINOS_STREAM_STATE_READY, NULL); - g_object_unref (stream); - - return; - - /* ERRORS */ -call_failed: - { - g_warning ("failed to release: %s", error->message); - stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error); - g_object_unref (stream); - return; - } -} - -static gboolean -do_stop (PinosStream *stream) -{ - PinosStreamPrivate *priv = stream->priv; - - g_dbus_proxy_call (priv->channel, - "Stop", - g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* GCancellable *cancellable */ - on_stream_stopped, - stream); - - return FALSE; -} -/** - * pinos_stream_stop: - * @stream: a #PinosStream - * - * Stop capturing from @stream. - * - * Returns: %TRUE on success. - */ -gboolean -pinos_stream_stop (PinosStream *stream) -{ - PinosStreamPrivate *priv; - - g_return_val_if_fail (PINOS_IS_STREAM (stream), FALSE); - - priv = stream->priv; - g_return_val_if_fail (priv->state == PINOS_STREAM_STATE_STREAMING, FALSE); - - g_main_context_invoke (priv->context->priv->context, - (GSourceFunc) do_stop, - g_object_ref (stream)); - - return TRUE; -} - /** * pinos_stream_peek_buffer: * @stream: a #PinosStream diff --git a/pinos/client/subscribe.c b/pinos/client/subscribe.c index 50a6b6193..37a63e8a8 100644 --- a/pinos/client/subscribe.c +++ b/pinos/client/subscribe.c @@ -111,9 +111,6 @@ notify_event (PinosSubscribe *subscribe, else if (g_strcmp0 (interface_name, "org.pinos.Port1") == 0) { flags = PINOS_SUBSCRIPTION_FLAG_PORT; } - else if (g_strcmp0 (interface_name, "org.pinos.Channel1") == 0) { - flags = PINOS_SUBSCRIPTION_FLAG_CHANNEL; - } g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event, flags, data->proxy); } diff --git a/pinos/client/subscribe.h b/pinos/client/subscribe.h index b022000d5..245c6ab2b 100644 --- a/pinos/client/subscribe.h +++ b/pinos/client/subscribe.h @@ -48,11 +48,10 @@ 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_CHANNEL = (1 << 4), + PINOS_SUBSCRIPTION_FLAG_PORT = (1 << 3) } PinosSubscriptionFlags; -#define PINOS_SUBSCRIPTION_FLAGS_ALL 0x1f +#define PINOS_SUBSCRIPTION_FLAGS_ALL 0x0f typedef enum { PINOS_SUBSCRIPTION_EVENT_NEW = 0, diff --git a/pinos/dbus/org.pinos.xml b/pinos/dbus/org.pinos.xml index 9dd7f2230..983882ea7 100644 --- a/pinos/dbus/org.pinos.xml +++ b/pinos/dbus/org.pinos.xml @@ -53,21 +53,17 @@ Disconnect the client from the server. --> - - - - - + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pinos/modules/gst/gst-manager.c b/pinos/modules/gst/gst-manager.c index f7a48d90e..56b022997 100644 --- a/pinos/modules/gst/gst-manager.c +++ b/pinos/modules/gst/gst-manager.c @@ -65,7 +65,7 @@ device_added (PinosGstManager *manager, PinosGstManagerPrivate *priv = manager->priv; gchar *name, *klass; GstElement *element; - PinosNode *node = NULL; + PinosServerNode *node = NULL; GstStructure *p; PinosProperties *properties; GstCaps *caps; @@ -108,7 +108,7 @@ device_added (PinosGstManager *manager, caps); } if (node) - g_object_set_data (G_OBJECT (device), "PinosNode", node); + g_object_set_data (G_OBJECT (device), "PinosServerNode", node); pinos_properties_free (properties); gst_caps_unref (caps); @@ -121,7 +121,7 @@ device_removed (PinosGstManager *manager, GstDevice *device) { gchar *name; - PinosNode *node; + PinosServerNode *node; name = gst_device_get_display_name (device); if (strcmp (name, "gst") == 0) @@ -129,7 +129,7 @@ device_removed (PinosGstManager *manager, g_print("Device removed: %s\n", name); - node = g_object_steal_data (G_OBJECT (device), "PinosNode"); + node = g_object_steal_data (G_OBJECT (device), "PinosServerNode"); g_object_unref (node); g_free (name); } diff --git a/pinos/modules/gst/gst-sink.c b/pinos/modules/gst/gst-sink.c index eabc5eede..9527559bf 100644 --- a/pinos/modules/gst/gst-sink.c +++ b/pinos/modules/gst/gst-sink.c @@ -41,8 +41,6 @@ struct _PinosGstSinkPrivate GstNetTimeProvider *provider; PinosProperties *props; - - gint n_channels; }; enum { @@ -51,7 +49,7 @@ enum { PROP_POSSIBLE_FORMATS }; -G_DEFINE_TYPE (PinosGstSink, pinos_gst_sink, PINOS_TYPE_NODE); +G_DEFINE_TYPE (PinosGstSink, pinos_gst_sink, PINOS_TYPE_SERVER_NODE); static gboolean bus_handler (GstBus *bus, @@ -143,6 +141,7 @@ setup_pipeline (PinosGstSink *sink, GError **error) return TRUE; } +#if 0 static gboolean start_pipeline (PinosGstSink *sink, GError **error) { @@ -186,6 +185,7 @@ ready_failed: return FALSE; } } +#endif static void stop_pipeline (PinosGstSink *sink) @@ -240,11 +240,13 @@ set_state (PinosNode *node, return TRUE; } +#if 0 static void on_socket_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { + PinosNode *node = user_data; PinosGstSink *sink = user_data; PinosGstSinkPrivate *priv = sink->priv; GSocket *socket; @@ -268,7 +270,7 @@ on_socket_notify (GObject *gobject, } if (num_handles == 0) { - pinos_node_report_idle (PINOS_NODE (sink)); + pinos_node_report_idle (node); g_object_set (priv->depay, "caps", NULL, NULL); str = gst_caps_to_string (priv->possible_formats); @@ -298,7 +300,7 @@ on_socket_notify (GObject *gobject, } /* this is what we use as the final format for the output */ g_object_set (gobject, "format", format, NULL); - pinos_node_report_busy (PINOS_NODE (sink)); + pinos_node_report_busy (node); g_object_unref (socket); } @@ -310,31 +312,7 @@ on_socket_notify (GObject *gobject, g_object_set (gobject, "properties", props, NULL); pinos_properties_free (props); } - -static void -on_channel_added (PinosPort *port, PinosChannel *channel, PinosGstSink *sink) -{ - PinosGstSinkPrivate *priv = sink->priv; - GError *error = NULL; - - if (priv->n_channels == 0) { - if (!start_pipeline (sink, &error)) - return; - } - - g_signal_connect (channel, "notify::socket", (GCallback) on_socket_notify, sink); - priv->n_channels++; -} - -static void -on_channel_removed (PinosPort *port, PinosChannel *channel, PinosGstSink *sink) -{ - PinosGstSinkPrivate *priv = sink->priv; - - priv->n_channels--; - if (priv->n_channels == 0) - stop_pipeline (sink); -} +#endif static void get_property (GObject *object, @@ -384,10 +362,23 @@ set_property (GObject *object, } } +static void +on_input_port_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + PinosNode *node = PINOS_NODE (source_object); + PinosGstSinkPrivate *priv = PINOS_GST_SINK (node)->priv; + + priv->input = pinos_node_create_port_finish (node, res, NULL); +} + + + static void sink_constructed (GObject * object) { - PinosNode *node = PINOS_NODE (object); + PinosServerNode *node = PINOS_SERVER_NODE (object); PinosGstSink *sink = PINOS_GST_SINK (object); PinosGstSinkPrivate *priv = sink->priv; gchar *str; @@ -398,19 +389,16 @@ sink_constructed (GObject * object) str = gst_caps_to_string (priv->possible_formats); format = g_bytes_new_take (str, strlen (str) + 1); - priv->input = pinos_port_new (pinos_node_get_daemon (node), - pinos_node_get_object_path (node), - PINOS_DIRECTION_INPUT, - "input", - format, - NULL); + pinos_node_create_port (PINOS_NODE (node), + PINOS_DIRECTION_INPUT, + "input", + format, + NULL, + NULL, + on_input_port_created, + node); g_bytes_unref (format); - pinos_node_add_port (node, priv->input); - - g_signal_connect (priv->input, "channel-added", (GCallback) on_channel_added, sink); - g_signal_connect (priv->input, "channel-removed", (GCallback) on_channel_removed, sink); - setup_pipeline (sink, NULL); } @@ -471,14 +459,14 @@ pinos_gst_sink_init (PinosGstSink * sink) priv->props = pinos_properties_new (NULL, NULL); } -PinosNode * +PinosServerNode * pinos_gst_sink_new (PinosDaemon *daemon, const gchar *name, PinosProperties *properties, GstElement *element, GstCaps *caps) { - PinosNode *node; + PinosServerNode *node; node = g_object_new (PINOS_TYPE_GST_SINK, "daemon", daemon, diff --git a/pinos/modules/gst/gst-sink.h b/pinos/modules/gst/gst-sink.h index 414739d7b..6fcb02d1d 100644 --- a/pinos/modules/gst/gst-sink.h +++ b/pinos/modules/gst/gst-sink.h @@ -23,7 +23,7 @@ #include #include -#include +#include G_BEGIN_DECLS @@ -41,22 +41,22 @@ typedef struct _PinosGstSinkClass PinosGstSinkClass; typedef struct _PinosGstSinkPrivate PinosGstSinkPrivate; struct _PinosGstSink { - PinosNode object; + PinosServerNode object; PinosGstSinkPrivate *priv; }; struct _PinosGstSinkClass { - PinosNodeClass parent_class; + PinosServerNodeClass parent_class; }; -GType pinos_gst_sink_get_type (void); +GType pinos_gst_sink_get_type (void); -PinosNode * pinos_gst_sink_new (PinosDaemon *daemon, - const gchar *name, - PinosProperties *properties, - GstElement *element, - GstCaps *caps); +PinosServerNode * pinos_gst_sink_new (PinosDaemon *daemon, + const gchar *name, + PinosProperties *properties, + GstElement *element, + GstCaps *caps); G_END_DECLS diff --git a/pinos/modules/gst/gst-source.c b/pinos/modules/gst/gst-source.c index ee0866f24..fdd93d6cc 100644 --- a/pinos/modules/gst/gst-source.c +++ b/pinos/modules/gst/gst-source.c @@ -41,8 +41,6 @@ struct _PinosGstSourcePrivate GstNetTimeProvider *provider; PinosProperties *props; - - gint n_channels; }; enum { @@ -51,7 +49,7 @@ enum { PROP_POSSIBLE_FORMATS }; -G_DEFINE_TYPE (PinosGstSource, pinos_gst_source, PINOS_TYPE_NODE); +G_DEFINE_TYPE (PinosGstSource, pinos_gst_source, PINOS_TYPE_SERVER_NODE); static gboolean bus_handler (GstBus *bus, @@ -144,6 +142,7 @@ setup_pipeline (PinosGstSource *source, GError **error) return TRUE; } +#if 0 static gboolean start_pipeline (PinosGstSource *source, GError **error) { @@ -183,6 +182,7 @@ ready_failed: return FALSE; } } +#endif static void stop_pipeline (PinosGstSource *source) @@ -286,6 +286,7 @@ set_state (PinosNode *node, return TRUE; } +#if 0 static void on_socket_notify (GObject *gobject, GParamSpec *pspec, @@ -363,31 +364,7 @@ on_socket_notify (GObject *gobject, g_object_set (gobject, "properties", props, NULL); pinos_properties_free (props); } - -static void -on_channel_added (PinosPort *port, PinosChannel *channel, PinosGstSource *source) -{ - PinosGstSourcePrivate *priv = source->priv; - GError *error = NULL; - - if (priv->n_channels == 0) { - if (!start_pipeline (source, &error)) - return; - } - - g_signal_connect (channel, "notify::socket", (GCallback) on_socket_notify, source); - priv->n_channels++; -} - -static void -on_channel_removed (PinosPort *port, PinosChannel *channel, PinosGstSource *source) -{ - PinosGstSourcePrivate *priv = source->priv; - - priv->n_channels--; - if (priv->n_channels == 0) - stop_pipeline (source); -} +#endif static void get_property (GObject *object, @@ -437,10 +414,21 @@ set_property (GObject *object, } } +static void +on_output_port_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + PinosNode *node = PINOS_NODE (source_object); + PinosGstSourcePrivate *priv = PINOS_GST_SOURCE (node)->priv; + + priv->output = pinos_node_create_port_finish (node, res, NULL); +} + static void source_constructed (GObject * object) { - PinosNode *node = PINOS_NODE (object); + PinosServerNode *node = PINOS_SERVER_NODE (object); PinosGstSource *source = PINOS_GST_SOURCE (object); PinosGstSourcePrivate *priv = source->priv; gchar *str; @@ -451,30 +439,27 @@ source_constructed (GObject * object) str = gst_caps_to_string (priv->possible_formats); format = g_bytes_new_take (str, strlen (str) + 1); - priv->output = pinos_port_new (pinos_node_get_daemon (node), - pinos_node_get_object_path (node), - PINOS_DIRECTION_OUTPUT, - "output", - format, - NULL); + pinos_node_create_port (PINOS_NODE (node), + PINOS_DIRECTION_OUTPUT, + "output", + format, + NULL, + NULL, + on_output_port_created, + node); g_bytes_unref (format); - g_signal_connect (priv->output, "channel-added", (GCallback) on_channel_added, source); - g_signal_connect (priv->output, "channel-removed", (GCallback) on_channel_removed, source); - - pinos_node_add_port (node, priv->output); - setup_pipeline (source, NULL); } static void source_finalize (GObject * object) { - PinosNode *node = PINOS_NODE (object); + PinosServerNode *node = PINOS_SERVER_NODE (object); PinosGstSource *source = PINOS_GST_SOURCE (object); PinosGstSourcePrivate *priv = source->priv; - pinos_node_remove_port (node, priv->output); + pinos_node_remove_port (PINOS_NODE (node), priv->output); destroy_pipeline (source); g_clear_pointer (&priv->possible_formats, gst_caps_unref); pinos_properties_free (priv->props); @@ -526,14 +511,14 @@ pinos_gst_source_init (PinosGstSource * source) priv->props = pinos_properties_new (NULL, NULL); } -PinosNode * +PinosServerNode * pinos_gst_source_new (PinosDaemon *daemon, const gchar *name, PinosProperties *properties, GstElement *element, GstCaps *caps) { - PinosNode *node; + PinosServerNode *node; node = g_object_new (PINOS_TYPE_GST_SOURCE, "daemon", daemon, diff --git a/pinos/modules/gst/gst-source.h b/pinos/modules/gst/gst-source.h index 4e3d8fc56..130c0268a 100644 --- a/pinos/modules/gst/gst-source.h +++ b/pinos/modules/gst/gst-source.h @@ -23,7 +23,7 @@ #include #include -#include +#include G_BEGIN_DECLS @@ -41,22 +41,22 @@ typedef struct _PinosGstSourceClass PinosGstSourceClass; typedef struct _PinosGstSourcePrivate PinosGstSourcePrivate; struct _PinosGstSource { - PinosNode object; + PinosServerNode object; PinosGstSourcePrivate *priv; }; struct _PinosGstSourceClass { - PinosNodeClass parent_class; + PinosServerNodeClass parent_class; }; -GType pinos_gst_source_get_type (void); +GType pinos_gst_source_get_type (void); -PinosNode * pinos_gst_source_new (PinosDaemon *daemon, - const gchar *name, - PinosProperties *properties, - GstElement *element, - GstCaps *caps); +PinosServerNode * pinos_gst_source_new (PinosDaemon *daemon, + const gchar *name, + PinosProperties *properties, + GstElement *element, + GstCaps *caps); G_END_DECLS diff --git a/pinos/server/channel.c b/pinos/server/channel.c deleted file mode 100644 index bf4dc6a1f..000000000 --- a/pinos/server/channel.c +++ /dev/null @@ -1,582 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * 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 -#include - -#include - -#include "pinos/client/enumtypes.h" - -#include "pinos/server/daemon.h" -#include "pinos/server/channel.h" - -#include "pinos/dbus/org-pinos.h" - -struct _PinosChannelPrivate -{ - PinosDaemon *daemon; - PinosChannel1 *iface; - - gchar *object_path; - gchar *client_path; - gchar *port_path; - PinosDirection direction; - - GBytes *possible_formats; - PinosProperties *properties; - GBytes *requested_format; - PinosChannelState state; - GBytes *format; - - GSocket *socket; -}; - -#define PINOS_CHANNEL_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_CHANNEL, PinosChannelPrivate)) - -G_DEFINE_TYPE (PinosChannel, pinos_channel, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_OBJECT_PATH, - PROP_CLIENT_PATH, - PROP_PORT_PATH, - PROP_DIRECTION, - PROP_POSSIBLE_FORMATS, - PROP_PROPERTIES, - PROP_REQUESTED_FORMAT, - PROP_FORMAT, - PROP_SOCKET, - PROP_STATE, -}; - -enum -{ - SIGNAL_REMOVE, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -pinos_channel_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosChannel *channel = PINOS_CHANNEL (_object); - PinosChannelPrivate *priv = channel->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - - case PROP_CLIENT_PATH: - g_value_set_string (value, priv->client_path); - break; - - case PROP_PORT_PATH: - g_value_set_string (value, priv->port_path); - break; - - case PROP_DIRECTION: - g_value_set_enum (value, priv->direction); - break; - - case PROP_POSSIBLE_FORMATS: - g_value_set_boxed (value, priv->possible_formats); - break; - - case PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - - case PROP_REQUESTED_FORMAT: - g_value_set_boxed (value, priv->requested_format); - break; - - case PROP_FORMAT: - g_value_set_boxed (value, priv->format); - break; - - case PROP_SOCKET: - g_value_set_object (value, priv->socket); - break; - - case PROP_STATE: - g_value_set_uint (value, priv->state); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (channel, prop_id, pspec); - break; - } -} - -static void -pinos_channel_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosChannel *channel = PINOS_CHANNEL (_object); - PinosChannelPrivate *priv = channel->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_OBJECT_PATH: - priv->object_path = g_value_dup_string (value); - break; - - case PROP_CLIENT_PATH: - priv->client_path = g_value_dup_string (value); - g_object_set (priv->iface, "client", priv->client_path, NULL); - break; - - case PROP_PORT_PATH: - priv->port_path = g_value_dup_string (value); - g_object_set (priv->iface, "port", priv->port_path, NULL); - break; - - case PROP_DIRECTION: - priv->direction = g_value_get_enum (value); - g_object_set (priv->iface, "direction", priv->direction, NULL); - break; - - case PROP_POSSIBLE_FORMATS: - if (priv->possible_formats) - g_bytes_unref (priv->possible_formats); - priv->possible_formats = g_value_dup_boxed (value); - g_object_set (priv->iface, "possible-formats", - g_bytes_get_data (priv->possible_formats, NULL), NULL); - break; - - case PROP_PROPERTIES: - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = g_value_dup_boxed (value); - g_object_set (priv->iface, "properties", priv->properties ? - pinos_properties_to_variant (priv->properties) : NULL, NULL); - break; - - case PROP_FORMAT: - if (priv->format) - g_bytes_unref (priv->format); - priv->format = g_value_dup_boxed (value); - g_object_set (priv->iface, "format", priv->format ? - g_bytes_get_data (priv->format, NULL) : NULL, NULL); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (channel, prop_id, pspec); - break; - } -} - -static void -clear_formats (PinosChannel *channel) -{ - PinosChannelPrivate *priv = channel->priv; - - g_debug ("channel %p: clear format", channel); - - g_clear_pointer (&priv->requested_format, g_bytes_unref); - g_clear_pointer (&priv->format, g_bytes_unref); -} - -static void -stop_transfer (PinosChannel *channel) -{ - PinosChannelPrivate *priv = channel->priv; - - g_debug ("channel %p: stop transfer", channel); - - if (priv->socket) { - g_clear_object (&priv->socket); - g_object_notify (G_OBJECT (channel), "socket"); - } - clear_formats (channel); - priv->state = PINOS_CHANNEL_STATE_STOPPED; - g_object_set (priv->iface, - "state", priv->state, - NULL); -} - -static gboolean -handle_start (PinosChannel1 *interface, - GDBusMethodInvocation *invocation, - const gchar *arg_requested_format, - gpointer user_data) -{ - PinosChannel *channel = user_data; - PinosChannelPrivate *priv = channel->priv; - GUnixFDList *fdlist; - gint fd[2]; - const gchar *format; - - priv->state = PINOS_CHANNEL_STATE_STARTING; - - priv->requested_format = g_bytes_new (arg_requested_format, - strlen (arg_requested_format) + 1); - - socketpair (AF_UNIX, SOCK_STREAM, 0, fd); - - g_debug ("channel %p: handle start, fd[%d,%d], format %s", channel, fd[0], fd[1], arg_requested_format); - - g_clear_object (&priv->socket); - priv->socket = g_socket_new_from_fd (fd[0], NULL); - g_object_set_data (G_OBJECT (priv->socket), "pinos-client-path", priv->client_path); - - g_debug ("channel %p: notify socket %p, path %s", channel, priv->socket, priv->client_path); - g_object_notify (G_OBJECT (channel), "socket"); - - /* the notify of the socket above should configure the format */ - if (priv->format == NULL) - goto no_format; - - format = g_bytes_get_data (priv->format, NULL); - - priv->state = PINOS_CHANNEL_STATE_STREAMING; - g_debug ("channel %p: we are now streaming in format \"%s\"", channel, format); - - 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 ("(hs@a{sv})", - 0, - format, - pinos_properties_to_variant (priv->properties)), - fdlist); - g_object_unref (fdlist); - close (fd[1]); - - g_object_set (priv->iface, - "format", format, - "state", priv->state, - NULL); - - return TRUE; - - /* error */ -no_format: - { - g_debug ("channel %p: no format configured", channel); - g_dbus_method_invocation_return_dbus_error (invocation, - "org.pinos.Error", "No format"); - close (fd[0]); - close (fd[1]); - g_clear_pointer (&priv->requested_format, g_bytes_unref); - g_clear_object (&priv->socket); - return TRUE; - } -} - -static gboolean -handle_stop (PinosChannel1 *interface, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - PinosChannel *channel = user_data; - - g_debug ("channel %p: handle stop", channel); - stop_transfer (channel); - - g_dbus_method_invocation_return_value (invocation, NULL); - - return TRUE; -} - -static gboolean -handle_remove (PinosChannel1 *interface, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - PinosChannel *channel = user_data; - - g_debug ("channel %p: handle remove", channel); - stop_transfer (channel); - - g_signal_emit (channel, signals[SIGNAL_REMOVE], 0, NULL); - - g_dbus_method_invocation_return_value (invocation, NULL); - - return TRUE; -} - -static void -channel_register_object (PinosChannel *channel) -{ - PinosChannelPrivate *priv = channel->priv; - PinosObjectSkeleton *skel; - gchar *name; - - name = g_strdup_printf ("%s/channel", priv->client_path); - skel = pinos_object_skeleton_new (name); - g_free (name); - - pinos_object_skeleton_set_channel1 (skel, priv->iface); - - g_free (priv->object_path); - priv->object_path = pinos_daemon_export_uniquely (priv->daemon, G_DBUS_OBJECT_SKELETON (skel)); - g_object_unref (skel); - - g_debug ("channel %p: register object %s", channel, priv->object_path); -} - -static void -channel_unregister_object (PinosChannel *channel) -{ - PinosChannelPrivate *priv = channel->priv; - - g_debug ("channel %p: unregister object", channel); - pinos_daemon_unexport (priv->daemon, priv->object_path); -} - -static void -pinos_channel_dispose (GObject * object) -{ - PinosChannel *channel = PINOS_CHANNEL (object); - PinosChannelPrivate *priv = channel->priv; - - g_debug ("channel %p: dispose", channel); - clear_formats (channel); - g_clear_object (&priv->socket); - channel_unregister_object (channel); - - G_OBJECT_CLASS (pinos_channel_parent_class)->dispose (object); -} - -static void -pinos_channel_finalize (GObject * object) -{ - PinosChannel *channel = PINOS_CHANNEL (object); - PinosChannelPrivate *priv = channel->priv; - - g_debug ("channel %p: finalize", channel); - if (priv->possible_formats) - g_bytes_unref (priv->possible_formats); - if (priv->properties) - pinos_properties_free (priv->properties); - g_clear_object (&priv->daemon); - g_clear_object (&priv->iface); - g_free (priv->client_path); - g_free (priv->object_path); - g_free (priv->port_path); - - G_OBJECT_CLASS (pinos_channel_parent_class)->finalize (object); -} - -static void -pinos_channel_constructed (GObject * object) -{ - PinosChannel *channel = PINOS_CHANNEL (object); - - g_debug ("channel %p: constructed", channel); - channel_register_object (channel); - - G_OBJECT_CLASS (pinos_channel_parent_class)->constructed (object); -} - -static void -pinos_channel_class_init (PinosChannelClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosChannelPrivate)); - - gobject_class->constructed = pinos_channel_constructed; - gobject_class->dispose = pinos_channel_dispose; - gobject_class->finalize = pinos_channel_finalize; - gobject_class->set_property = pinos_channel_set_property; - gobject_class->get_property = pinos_channel_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_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_CLIENT_PATH, - g_param_spec_string ("client-path", - "Client Path", - "The client object path", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_PORT_PATH, - g_param_spec_string ("port-path", - "Port Path", - "The port object path", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_DIRECTION, - g_param_spec_enum ("direction", - "Direction", - "The direction of the port", - PINOS_TYPE_DIRECTION, - PINOS_DIRECTION_INVALID, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_POSSIBLE_FORMATS, - g_param_spec_boxed ("possible-formats", - "Possible Formats", - "The possbile formats of the stream", - G_TYPE_BYTES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_PROPERTIES, - g_param_spec_boxed ("properties", - "Properties", - "Extra properties of the stream", - PINOS_TYPE_PROPERTIES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_REQUESTED_FORMAT, - g_param_spec_boxed ("requested-format", - "Requested Format", - "The requested format of the stream", - G_TYPE_BYTES, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_FORMAT, - g_param_spec_boxed ("format", - "Format", - "The format of the stream", - G_TYPE_BYTES, - G_PARAM_READWRITE | - 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)); - - signals[SIGNAL_REMOVE] = g_signal_new ("remove", - 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_channel_init (PinosChannel * channel) -{ - PinosChannelPrivate *priv = channel->priv = PINOS_CHANNEL_GET_PRIVATE (channel); - - priv->iface = pinos_channel1_skeleton_new (); - g_signal_connect (priv->iface, "handle-start", (GCallback) handle_start, channel); - g_signal_connect (priv->iface, "handle-stop", (GCallback) handle_stop, channel); - g_signal_connect (priv->iface, "handle-remove", (GCallback) handle_remove, channel); - - priv->state = PINOS_CHANNEL_STATE_STOPPED; - g_object_set (priv->iface, "state", priv->state, NULL); - - priv->direction = PINOS_DIRECTION_INVALID; - - g_debug ("channel %p: new", channel); -} - -/** - * pinos_channel_remove: - * @channel: a #PinosChannel - * - * Remove @channel. This will stop the transfer on the channel and - * free the resources allocated by @channel. - */ -void -pinos_channel_remove (PinosChannel *channel) -{ - g_debug ("channel %p: remove", channel); - stop_transfer (channel); - - g_signal_emit (channel, signals[SIGNAL_REMOVE], 0, NULL); -} - -/** - * pinos_channel_get_object_path: - * @channel: a #PinosChannel - * - * Get the object patch of @channel - * - * Returns: the object path of @source. - */ -const gchar * -pinos_channel_get_object_path (PinosChannel *channel) -{ - PinosChannelPrivate *priv; - - g_return_val_if_fail (PINOS_IS_CHANNEL (channel), NULL); - priv = channel->priv; - - return priv->object_path; -} diff --git a/pinos/server/channel.h b/pinos/server/channel.h deleted file mode 100644 index 66e1aac51..000000000 --- a/pinos/server/channel.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * 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_CHANNEL_H__ -#define __PINOS_CHANNEL_H__ - -#include - -G_BEGIN_DECLS - -#define PINOS_TYPE_CHANNEL (pinos_channel_get_type ()) -#define PINOS_IS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_CHANNEL)) -#define PINOS_IS_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_CHANNEL)) -#define PINOS_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_CHANNEL, PinosChannelClass)) -#define PINOS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_CHANNEL, PinosChannel)) -#define PINOS_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_CHANNEL, PinosChannelClass)) -#define PINOS_CHANNEL_CAST(obj) ((PinosChannel*)(obj)) -#define PINOS_CHANNEL_CLASS_CAST(klass) ((PinosChannelClass*)(klass)) - -typedef struct _PinosChannel PinosChannel; -typedef struct _PinosChannelClass PinosChannelClass; -typedef struct _PinosChannelPrivate PinosChannelPrivate; - -/** - * PinosChannel: - * - * Pinos source channel object class. - */ -struct _PinosChannel { - GObject object; - - PinosChannelPrivate *priv; -}; - -/** - * PinosChannelClass: - * - * Pinos source channel object class. - */ -struct _PinosChannelClass { - GObjectClass parent_class; -}; - -/* normal GObject stuff */ -GType pinos_channel_get_type (void); - -void pinos_channel_remove (PinosChannel *channel); - -const gchar * pinos_channel_get_object_path (PinosChannel *channel); - -G_END_DECLS - -#endif /* __PINOS_CHANNEL_H__ */ diff --git a/pinos/server/client.c b/pinos/server/client.c index 11f233471..a55f5f748 100644 --- a/pinos/server/client.c +++ b/pinos/server/client.c @@ -21,6 +21,7 @@ #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" @@ -35,7 +36,8 @@ struct _PinosClientPrivate PinosProperties *properties; PinosFdManager *fdmanager; - GList *channels; + + GList *nodes; }; #define PINOS_CLIENT_GET_PRIVATE(obj) \ @@ -126,73 +128,53 @@ pinos_client_set_property (GObject *_object, } static void -handle_remove_channel (PinosChannel *channel, - gpointer user_data) +handle_remove_node (PinosNode *node, + gpointer user_data) { PinosClient *client = user_data; PinosClientPrivate *priv = client->priv; - g_debug ("client %p: remove channel %p", client, channel); - priv->channels = g_list_remove (priv->channels, channel); - g_object_unref (channel); + 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_channel (PinosClient1 *interface, - GDBusMethodInvocation *invocation, - PinosDirection direction, - const gchar *arg_port, - const gchar *arg_possible_formats, - GVariant *arg_properties, - gpointer user_data) +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; - PinosPort *port; - PinosChannel *channel; + PinosNode *node; const gchar *object_path, *sender; - GBytes *formats; PinosProperties *props; - GError *error = NULL; sender = g_dbus_method_invocation_get_sender (invocation); if (g_strcmp0 (pinos_client_get_sender (client), sender) != 0) goto not_allowed; - formats = g_bytes_new (arg_possible_formats, strlen (arg_possible_formats) + 1); props = pinos_properties_from_variant (arg_properties); - - port = pinos_daemon_find_port (priv->daemon, - direction, - arg_port, - props, - formats, - &error); - if (port == NULL) - goto no_port; - - g_debug ("client %p: matched port %s", client, pinos_port_get_object_path (port)); - - channel = pinos_port_create_channel (port, - priv->object_path, - formats, - props, - &error); + node = pinos_server_node_new (priv->daemon, + sender, + arg_name, + props); pinos_properties_free (props); - g_bytes_unref (formats); - if (channel == NULL) - goto no_channel; + if (node == NULL) + goto no_node; - priv->channels = g_list_prepend (priv->channels, channel); + priv->nodes = g_list_prepend (priv->nodes, node); - g_signal_connect (channel, + g_signal_connect (node, "remove", - (GCallback) handle_remove_channel, + (GCallback) handle_remove_node, client); - object_path = pinos_channel_get_object_path (channel); - g_debug ("client %p: add source channel %p, %s", client, channel, object_path); + object_path = pinos_server_node_get_object_path (PINOS_SERVER_NODE (node)); + g_debug ("client %p: add node %p, %s", client, node, object_path); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", object_path)); @@ -201,112 +183,21 @@ handle_create_channel (PinosClient1 *interface, /* 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", "not client owner"); - return TRUE; - } -no_port: - { - g_debug ("client %p: could not find port %s, %s", client, arg_port, error->message); - g_dbus_method_invocation_return_gerror (invocation, error); - pinos_properties_free (props); - g_bytes_unref (formats); - g_clear_error (&error); - return TRUE; - } -no_channel: - { - g_debug ("client %p: could not create channel %s", client, error->message); - g_dbus_method_invocation_return_gerror (invocation, error); - g_clear_error (&error); - return TRUE; - } -} - -static gboolean -handle_create_upload_channel (PinosClient1 *interface, - GDBusMethodInvocation *invocation, - const gchar *arg_possible_formats, - GVariant *arg_properties, - gpointer user_data) -{ - PinosClient *client = user_data; - PinosClientPrivate *priv = client->priv; - PinosNode *node; - PinosChannel *channel; - const gchar *channel_path, *sender; - GBytes *formats; - GError *error = NULL; - PinosProperties *props; - - sender = g_dbus_method_invocation_get_sender (invocation); - if (g_strcmp0 (pinos_client_get_sender (client), sender) != 0) - goto not_allowed; - - formats = g_bytes_new (arg_possible_formats, strlen (arg_possible_formats) + 1); - - node = pinos_upload_node_new (priv->daemon, formats); - if (node == NULL) - goto no_node; - - sender = g_dbus_method_invocation_get_sender (invocation); - props = pinos_properties_from_variant (arg_properties); - - channel = pinos_upload_node_get_channel (PINOS_UPLOAD_NODE (node), - priv->object_path, - formats, - props, - &error); - pinos_properties_free (props); - - if (channel == NULL) - goto no_channel; - - g_object_set_data_full (G_OBJECT (channel), - "channel-owner", - node, - g_object_unref); - - channel_path = pinos_channel_get_object_path (channel); - g_debug ("client %p: add source channel %p, %s", client, channel, channel_path); - priv->channels = g_list_prepend (priv->channels, channel); - - g_signal_connect (channel, - "remove", - (GCallback) handle_remove_channel, - client); - - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(o)", - channel_path)); - - return TRUE; - - /* ERRORS */ -not_allowed: - { - g_dbus_method_invocation_return_dbus_error (invocation, - "org.pinos.Error", "not client owner"); + "org.pinos.Error", "sender not client owner"); return TRUE; } no_node: { - g_debug ("client %p: could not create upload node", client); + 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 upload node"); - g_bytes_unref (formats); - return TRUE; - } -no_channel: - { - g_debug ("client %p: could not create upload channel %s", client, error->message); - g_dbus_method_invocation_return_gerror (invocation, error); - g_object_unref (node); - g_clear_error (&error); - g_bytes_unref (formats); + "org.pinos.Error", "can't create node"); + pinos_properties_free (props); return TRUE; } } + static gboolean handle_disconnect (PinosClient1 *interface, GDBusMethodInvocation *invocation, @@ -360,8 +251,8 @@ pinos_client_dispose (GObject * object) g_debug ("client %p: dispose", client); pinos_fd_manager_remove_all (priv->fdmanager, priv->object_path); - copy = g_list_copy (priv->channels); - g_list_free_full (copy, (GDestroyNotify) pinos_channel_remove); + 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); @@ -466,11 +357,8 @@ 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-channel", - (GCallback) handle_create_channel, - client); - g_signal_connect (priv->iface, "handle-create-upload-channel", - (GCallback) handle_create_upload_channel, + g_signal_connect (priv->iface, "handle-create-node", + (GCallback) handle_create_node, client); g_signal_connect (priv->iface, "handle-disconnect", (GCallback) handle_disconnect, diff --git a/pinos/server/daemon.c b/pinos/server/daemon.c index f800736d7..8f4485f88 100644 --- a/pinos/server/daemon.c +++ b/pinos/server/daemon.c @@ -344,18 +344,18 @@ pinos_daemon_unexport (PinosDaemon *daemon, /** * pinos_daemon_add_node: * @daemon: a #PinosDaemon - * @node: a #PinosNode + * @node: a #PinosServerNode * * Add @node to @daemon. */ void -pinos_daemon_add_node (PinosDaemon *daemon, - PinosNode *node) +pinos_daemon_add_node (PinosDaemon *daemon, + PinosServerNode *node) { PinosDaemonPrivate *priv; g_return_if_fail (PINOS_IS_DAEMON (daemon)); - g_return_if_fail (PINOS_IS_NODE (node)); + g_return_if_fail (PINOS_IS_SERVER_NODE (node)); priv = daemon->priv; priv->nodes = g_list_prepend (priv->nodes, node); @@ -364,18 +364,18 @@ pinos_daemon_add_node (PinosDaemon *daemon, /** * pinos_daemon_remove_node: * @daemon: a #PinosDaemon - * @node: a #PinosNode + * @node: a #PinosServerNode * * Remove @node from @daemon. */ void -pinos_daemon_remove_node (PinosDaemon *daemon, - PinosNode *node) +pinos_daemon_remove_node (PinosDaemon *daemon, + PinosServerNode *node) { PinosDaemonPrivate *priv; g_return_if_fail (PINOS_IS_DAEMON (daemon)); - g_return_if_fail (PINOS_IS_NODE (node)); + g_return_if_fail (PINOS_IS_SERVER_NODE (node)); priv = daemon->priv; priv->nodes = g_list_remove (priv->nodes, node); @@ -391,9 +391,9 @@ pinos_daemon_remove_node (PinosDaemon *daemon, * * Find the best port in @daemon that matches the given parameters. * - * Returns: a #PinosPort or %NULL when no port could be found. + * Returns: a #PinosServerPort or %NULL when no port could be found. */ -PinosPort * +PinosServerPort * pinos_daemon_find_port (PinosDaemon *daemon, PinosDirection direction, const gchar *name, @@ -402,8 +402,8 @@ pinos_daemon_find_port (PinosDaemon *daemon, GError **error) { PinosDaemonPrivate *priv; - PinosPort *best = NULL; - GList *node, *port; + PinosServerPort *best = NULL; + GList *nodes, *ports; gboolean have_name; g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); @@ -411,18 +411,18 @@ pinos_daemon_find_port (PinosDaemon *daemon, have_name = name ? strlen (name) > 0 : FALSE; - for (node = priv->nodes; node; node = g_list_next (node)) { - PinosNode *n = node->data; + for (nodes = priv->nodes; nodes; nodes = g_list_next (nodes)) { + PinosServerNode *n = nodes->data; gboolean node_found = FALSE; /* we found the node */ - if (have_name && g_str_has_suffix (pinos_node_get_object_path (n), name)) { - g_debug ("name \"%s\" matches node %s", name, pinos_node_get_object_path (n)); + if (have_name && g_str_has_suffix (pinos_server_node_get_object_path (n), name)) { + g_debug ("name \"%s\" matches node %s", name, pinos_server_node_get_object_path (n)); node_found = TRUE; } - for (port = pinos_node_get_ports (n); port; port = g_list_next (port)) { - PinosPort *p = port->data; + for (ports = pinos_node_get_ports (PINOS_NODE (n)); ports; ports = g_list_next (ports)) { + PinosServerPort *p = ports->data; PinosDirection dir; GBytes *format; @@ -431,18 +431,18 @@ pinos_daemon_find_port (PinosDaemon *daemon, continue; if (have_name && !node_found) { - if (!g_str_has_suffix (pinos_port_get_object_path (p), name)) + if (!g_str_has_suffix (pinos_server_port_get_object_path (p), name)) continue; - g_debug ("name \"%s\" matches port %s", name, pinos_port_get_object_path (p)); + g_debug ("name \"%s\" matches port %s", name, pinos_server_port_get_object_path (p)); best = p; node_found = TRUE; break; } - format = pinos_port_get_formats (p, format_filter, NULL); + format = pinos_port_get_formats (PINOS_PORT (p), format_filter, NULL); if (format != NULL) { g_debug ("port %s with format %s matches filter %s", - pinos_port_get_object_path (p), + pinos_server_port_get_object_path (p), (gchar*)g_bytes_get_data (format, NULL), format_filter ? (gchar*)g_bytes_get_data (format_filter, NULL) : "ANY"); g_bytes_unref (format); diff --git a/pinos/server/daemon.h b/pinos/server/daemon.h index 31765bc82..f3561646c 100644 --- a/pinos/server/daemon.h +++ b/pinos/server/daemon.h @@ -37,8 +37,8 @@ typedef struct _PinosDaemon PinosDaemon; typedef struct _PinosDaemonClass PinosDaemonClass; typedef struct _PinosDaemonPrivate PinosDaemonPrivate; -#include -#include +#include +#include #include /** @@ -72,10 +72,10 @@ void pinos_daemon_stop (PinosDaemon *daemon); gchar * pinos_daemon_export_uniquely (PinosDaemon *daemon, GDBusObjectSkeleton *skel); void pinos_daemon_unexport (PinosDaemon *daemon, const gchar *name); -void pinos_daemon_add_node (PinosDaemon *daemon, PinosNode *node); -void pinos_daemon_remove_node (PinosDaemon *daemon, PinosNode *node); +void pinos_daemon_add_node (PinosDaemon *daemon, PinosServerNode *node); +void pinos_daemon_remove_node (PinosDaemon *daemon, PinosServerNode *node); -PinosPort * pinos_daemon_find_port (PinosDaemon *daemon, +PinosServerPort * pinos_daemon_find_port (PinosDaemon *daemon, PinosDirection direction, const gchar *name, PinosProperties *props, diff --git a/pinos/server/node.c b/pinos/server/node.c deleted file mode 100644 index 66582a1c7..000000000 --- a/pinos/server/node.c +++ /dev/null @@ -1,534 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * 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 - -#include "pinos/client/pinos.h" -#include "pinos/client/enumtypes.h" - -#include "pinos/server/node.h" -#include "pinos/server/daemon.h" - -#include "pinos/dbus/org-pinos.h" - - -#define PINOS_NODE_GET_PRIVATE(node) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((node), PINOS_TYPE_NODE, PinosNodePrivate)) - -struct _PinosNodePrivate -{ - PinosDaemon *daemon; - PinosNode1 *iface; - - gchar *object_path; - gchar *name; - - PinosNodeState state; - GError *error; - guint idle_timeout; - - PinosProperties *properties; - - GList *ports; -}; - -G_DEFINE_TYPE (PinosNode, pinos_node, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_OBJECT_PATH, - PROP_NAME, - PROP_STATE, - PROP_PROPERTIES, -}; - -static void -pinos_node_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosNode *node = PINOS_NODE (_object); - PinosNodePrivate *priv = node->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - - case PROP_STATE: - g_value_set_enum (value, priv->state); - break; - - case PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec); - break; - } -} - -static void -pinos_node_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosNode *node = PINOS_NODE (_object); - PinosNodePrivate *priv = node->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_NAME: - priv->name = g_value_dup_string (value); - pinos_node1_set_name (priv->iface, priv->name); - break; - - case PROP_PROPERTIES: - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = g_value_dup_boxed (value); - pinos_node1_set_properties (priv->iface, - priv->properties ? pinos_properties_to_variant (priv->properties) : NULL); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec); - break; - } -} - -static void -node_register_object (PinosNode *node) -{ - PinosNodePrivate *priv = node->priv; - PinosDaemon *daemon = priv->daemon; - PinosObjectSkeleton *skel; - - skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_NODE); - - pinos_object_skeleton_set_node1 (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 ("node %p: register object %s", node, priv->object_path); - pinos_daemon_add_node (daemon, node); - - return; -} - -static void -node_unregister_object (PinosNode *node) -{ - PinosNodePrivate *priv = node->priv; - - g_debug ("node %p: unregister object %s", node, priv->object_path); - pinos_daemon_unexport (priv->daemon, priv->object_path); - pinos_daemon_remove_node (priv->daemon, node); -} - -static void -pinos_node_constructed (GObject * obj) -{ - PinosNode *node = PINOS_NODE (obj); - - g_debug ("node %p: constructed", node); - node_register_object (node); - - G_OBJECT_CLASS (pinos_node_parent_class)->constructed (obj); -} - -static void -pinos_node_dispose (GObject * obj) -{ - PinosNode *node = PINOS_NODE (obj); - PinosNodePrivate *priv = node->priv; - - g_debug ("node %p: dispose", node); - g_list_free_full (priv->ports, (GDestroyNotify) g_object_unref); - priv->ports = NULL; - node_unregister_object (node); - - G_OBJECT_CLASS (pinos_node_parent_class)->dispose (obj); -} - -static void -pinos_node_finalize (GObject * obj) -{ - PinosNode *node = PINOS_NODE (obj); - PinosNodePrivate *priv = node->priv; - - g_debug ("node %p: finalize", node); - g_clear_object (&priv->daemon); - g_clear_object (&priv->iface); - g_free (priv->name); - g_free (priv->object_path); - g_clear_error (&priv->error); - if (priv->properties) - pinos_properties_free (priv->properties); - - G_OBJECT_CLASS (pinos_node_parent_class)->finalize (obj); -} - -static void -pinos_node_class_init (PinosNodeClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosNodePrivate)); - - gobject_class->constructed = pinos_node_constructed; - gobject_class->dispose = pinos_node_dispose; - gobject_class->finalize = pinos_node_finalize; - gobject_class->set_property = pinos_node_set_property; - gobject_class->get_property = pinos_node_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_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_NAME, - g_param_spec_string ("name", - "Name", - "The node name", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_STATE, - g_param_spec_enum ("state", - "State", - "The state of the node", - PINOS_TYPE_NODE_STATE, - PINOS_NODE_STATE_SUSPENDED, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_PROPERTIES, - g_param_spec_boxed ("properties", - "Properties", - "The properties of the node", - PINOS_TYPE_PROPERTIES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - -} - -static void -pinos_node_init (PinosNode * node) -{ - PinosNodePrivate *priv = node->priv = PINOS_NODE_GET_PRIVATE (node); - - g_debug ("node %p: new", node); - priv->state = PINOS_NODE_STATE_SUSPENDED; - - priv->iface = pinos_node1_skeleton_new (); - pinos_node1_set_state (priv->iface, priv->state); -} - -/** - * pinos_node_get_daemon: - * @node: a #PinosNode - * - * Get the daemon of @node. - * - * Returns: the daemon of @node. - */ -PinosDaemon * -pinos_node_get_daemon (PinosNode *node) -{ - PinosNodePrivate *priv; - - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; - - return priv->daemon; -} - -/** - * pinos_node_get_object_path: - * @node: a #PinosNode - * - * Get the object path of @node. - * - * Returns: the object path of @node. - */ -const gchar * -pinos_node_get_object_path (PinosNode *node) -{ - PinosNodePrivate *priv; - - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; - - return priv->object_path; -} - -/** - * pinos_node_add_port: - * @node: a #PinosNode - * @port: (transfer full): a #PinosPort - * - * Add the #PinosPort to @node - */ -void -pinos_node_add_port (PinosNode *node, PinosPort *port) -{ - PinosNodePrivate *priv; - - g_return_if_fail (PINOS_IS_NODE (node)); - g_return_if_fail (PINOS_IS_PORT (port)); - priv = node->priv; - - priv->ports = g_list_append (priv->ports, port); -} - -/** - * pinos_node_remove_port: - * @node: a #PinosNode - * @port: (transfer full): a #PinosPort - * - * Remove the #PinosPort from @node - */ -void -pinos_node_remove_port (PinosNode *node, PinosPort *port) -{ - PinosNodePrivate *priv; - GList *find; - - g_return_if_fail (PINOS_IS_NODE (node)); - g_return_if_fail (PINOS_IS_PORT (port)); - priv = node->priv; - - find = g_list_find (priv->ports, port); - if (find) { - priv->ports = g_list_delete_link (priv->ports, find); - g_object_unref (port); - } -} - -/** - * pinos_node_get_ports: - * @node: a #PinosNode - * - * Get the list of ports in @node. - * - * Returns: a #GList of nodes owned by @node. - */ -GList * -pinos_node_get_ports (PinosNode *node) -{ - PinosNodePrivate *priv; - - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; - - return priv->ports; -} - -static void -remove_idle_timeout (PinosNode *node) -{ - PinosNodePrivate *priv = node->priv; - - if (priv->idle_timeout) { - g_source_remove (priv->idle_timeout); - priv->idle_timeout = 0; - } -} - -/** - * pinos_node_set_state: - * @node: a #PinosNode - * @state: a #PinosNodeState - * - * Set the state of @node to @state. - * - * Returns: %TRUE on success. - */ -gboolean -pinos_node_set_state (PinosNode *node, - PinosNodeState state) -{ - PinosNodeClass *klass; - gboolean res; - - g_return_val_if_fail (PINOS_IS_NODE (node), FALSE); - - klass = PINOS_NODE_GET_CLASS (node); - - remove_idle_timeout (node); - - if (klass->set_state) - res = klass->set_state (node, state); - else - res = FALSE; - - return res; -} - -/** - * pinos_node_update_state: - * @node: a #PinosNode - * @state: a #PinosNodeState - * - * Update the state of a node. This method is used from - * inside @node itself. - */ -void -pinos_node_update_state (PinosNode *node, - PinosNodeState state) -{ - PinosNodePrivate *priv; - - g_return_if_fail (PINOS_IS_NODE (node)); - priv = node->priv; - - if (priv->state != state) { - priv->state = state; - pinos_node1_set_state (priv->iface, state); - g_object_notify (G_OBJECT (node), "state"); - } -} - -/** - * pinos_node_report_error: - * @node: a #PinosNode - * @error: a #GError - * - * Report an error from within @node. - */ -void -pinos_node_report_error (PinosNode *node, - GError *error) -{ - PinosNodePrivate *priv; - - g_return_if_fail (PINOS_IS_NODE (node)); - priv = node->priv; - - g_clear_error (&priv->error); - remove_idle_timeout (node); - priv->error = error; - priv->state = PINOS_NODE_STATE_ERROR; - g_debug ("got error state %s", error->message); - pinos_node1_set_state (priv->iface, priv->state); - g_object_notify (G_OBJECT (node), "state"); -} - -static gboolean -idle_timeout (PinosNode *node) -{ - PinosNodePrivate *priv = node->priv; - - priv->idle_timeout = 0; - pinos_node_set_state (node, PINOS_NODE_STATE_SUSPENDED); - - return G_SOURCE_REMOVE; -} - -/** - * pinos_node_report_idle: - * @node: a #PinosNode - * - * Mark @node as being idle. This will start a timeout that will - * set the node to SUSPENDED. - */ -void -pinos_node_report_idle (PinosNode *node) -{ - PinosNodePrivate *priv; - - g_return_if_fail (PINOS_IS_NODE (node)); - priv = node->priv; - - pinos_node_set_state (node, PINOS_NODE_STATE_IDLE); - - priv->idle_timeout = g_timeout_add_seconds (3, - (GSourceFunc) idle_timeout, - node); -} - -/** - * pinos_node_report_busy: - * @node: a #PinosNode - * - * Mark @node as being busy. This will set the state of the node - * to the RUNNING state. - */ -void -pinos_node_report_busy (PinosNode *node) -{ - g_return_if_fail (PINOS_IS_NODE (node)); - - pinos_node_set_state (node, PINOS_NODE_STATE_RUNNING); -} - -/** - * pinos_node_new: - * @daemon: a #PinosDaemon - * - * Make a new node - * - * Returns: a new #PinosNode - */ -PinosNode * -pinos_node_new (PinosDaemon *daemon) -{ - return g_object_new (PINOS_TYPE_NODE, - "daemon", daemon, - NULL); -} diff --git a/pinos/server/node.h b/pinos/server/node.h deleted file mode 100644 index 69b6b789f..000000000 --- a/pinos/server/node.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * 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_NODE_H__ -#define __PINOS_NODE_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _PinosNode PinosNode; -typedef struct _PinosNodeClass PinosNodeClass; -typedef struct _PinosNodePrivate PinosNodePrivate; - -#include -#include -#include -#include - -#define PINOS_TYPE_NODE (pinos_node_get_type ()) -#define PINOS_IS_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_NODE)) -#define PINOS_IS_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_NODE)) -#define PINOS_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_NODE, PinosNodeClass)) -#define PINOS_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_NODE, PinosNode)) -#define PINOS_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_NODE, PinosNodeClass)) -#define PINOS_NODE_CAST(obj) ((PinosNode*)(obj)) -#define PINOS_NODE_CLASS_CAST(klass) ((PinosNodeClass*)(klass)) - -/** - * PinosNode: - * - * Pinos node class. - */ -struct _PinosNode { - GObject object; - - PinosNodePrivate *priv; -}; - -/** - * PinosNodeClass: - * @set_state: called to change the current state of the node - * - * Pinos node class. - */ -struct _PinosNodeClass { - GObjectClass parent_class; - - gboolean (*set_state) (PinosNode *node, PinosNodeState state); - -}; - -/* normal GObject stuff */ -GType pinos_node_get_type (void); - -PinosNode * pinos_node_new (PinosDaemon *daemon); - -PinosDaemon * pinos_node_get_daemon (PinosNode *node); -const gchar * pinos_node_get_object_path (PinosNode *node); - -void pinos_node_add_port (PinosNode *node, - PinosPort *port); -void pinos_node_remove_port (PinosNode *node, - PinosPort *port); -GList * pinos_node_get_ports (PinosNode *node); - -gboolean pinos_node_set_state (PinosNode *node, PinosNodeState state); -void pinos_node_update_state (PinosNode *node, PinosNodeState state); - -void pinos_node_report_error (PinosNode *node, GError *error); -void pinos_node_report_idle (PinosNode *node); -void pinos_node_report_busy (PinosNode *node); - -G_END_DECLS - -#endif /* __PINOS_NODE_H__ */ diff --git a/pinos/server/port.c b/pinos/server/port.c deleted file mode 100644 index 0ea5b7cde..000000000 --- a/pinos/server/port.c +++ /dev/null @@ -1,623 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * 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 - -#include -#include - -#include "pinos/client/pinos.h" -#include "pinos/client/enumtypes.h" - -#include "pinos/server/port.h" -#include "pinos/server/node.h" - -#include "pinos/dbus/org-pinos.h" - -#define PINOS_PORT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_PORT, PinosPortPrivate)) - -struct _PinosPortPrivate -{ - PinosDaemon *daemon; - PinosPort1 *iface; - gchar *node_path; - gchar *object_path; - - gchar *name; - PinosDirection direction; - GBytes *possible_formats; - PinosProperties *properties; - - GList *channels; -}; - -G_DEFINE_TYPE (PinosPort, pinos_port, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_NODE_PATH, - PROP_OBJECT_PATH, - PROP_NAME, - PROP_DIRECTION, - PROP_POSSIBLE_FORMATS, - PROP_PROPERTIES -}; - -enum -{ - SIGNAL_FORMAT_REQUEST, - SIGNAL_CHANNEL_ADDED, - SIGNAL_CHANNEL_REMOVED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -pinos_port_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosPort *port = PINOS_PORT (_object); - PinosPortPrivate *priv = port->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - - case PROP_NODE_PATH: - g_value_set_string (value, priv->node_path); - break; - - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - - case PROP_DIRECTION: - g_value_set_enum (value, priv->direction); - break; - - case PROP_POSSIBLE_FORMATS: - g_value_set_boxed (value, priv->possible_formats); - break; - - case PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (port, prop_id, pspec); - break; - } -} - -static void -pinos_port_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosPort *port = PINOS_PORT (_object); - PinosPortPrivate *priv = port->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_NAME: - priv->name = g_value_dup_string (value); - g_object_set (priv->iface, "name", priv->name, NULL); - break; - - case PROP_NODE_PATH: - priv->node_path = g_value_dup_string (value); - g_object_set (priv->iface, "node", priv->name, NULL); - break; - - case PROP_DIRECTION: - priv->direction = g_value_get_enum (value); - g_object_set (priv->iface, "direction", priv->direction, NULL); - break; - - case PROP_POSSIBLE_FORMATS: - { - GList *walk; - - if (priv->possible_formats) - g_bytes_unref (priv->possible_formats); - priv->possible_formats = g_value_dup_boxed (value); - - g_object_set (priv->iface, "possible-formats", priv->possible_formats ? - g_bytes_get_data (priv->possible_formats, NULL) : NULL, - NULL); - - for (walk = priv->channels; walk; walk = g_list_next (walk)) - g_object_set (walk->data, "possible-formats", priv->possible_formats, NULL); - break; - } - - case PROP_PROPERTIES: - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = g_value_dup_boxed (value); - - g_object_set (priv->iface, - "properties", priv->properties ? - pinos_properties_to_variant (priv->properties) : NULL, - NULL); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (port, prop_id, pspec); - break; - } -} - -static void -port_register_object (PinosPort *port) -{ - PinosPortPrivate *priv = port->priv; - PinosObjectSkeleton *skel; - gchar *name; - - name = g_strdup_printf ("%s/port", priv->node_path); - skel = pinos_object_skeleton_new (name); - g_free (name); - - pinos_object_skeleton_set_port1 (skel, priv->iface); - - g_free (priv->object_path); - priv->object_path = pinos_daemon_export_uniquely (priv->daemon, - G_DBUS_OBJECT_SKELETON (skel)); - g_object_unref (skel); - g_debug ("port %p: register object %s", port, priv->object_path); - - return; -} - -static void -port_unregister_object (PinosPort *port) -{ - PinosPortPrivate *priv = port->priv; - - g_debug ("port %p: unregister object %s", port, priv->object_path); - pinos_daemon_unexport (priv->daemon, priv->object_path); -} - -static void -pinos_port_constructed (GObject * object) -{ - PinosPort *port = PINOS_PORT (object); - - port_register_object (port); - - G_OBJECT_CLASS (pinos_port_parent_class)->constructed (object); -} - -static void -pinos_port_dispose (GObject * object) -{ - PinosPort *port = PINOS_PORT (object); - PinosPortPrivate *priv = port->priv; - GList *copy; - - g_debug ("port %p: dispose", port); - - copy = g_list_copy (priv->channels); - g_list_free_full (copy, (GDestroyNotify) pinos_channel_remove); - port_unregister_object (port); - - G_OBJECT_CLASS (pinos_port_parent_class)->dispose (object); -} - -static void -pinos_port_finalize (GObject * object) -{ - PinosPort *port = PINOS_PORT (object); - PinosPortPrivate *priv = port->priv; - - g_debug ("port %p: finalize", port); - g_free (priv->name); - g_free (priv->object_path); - g_free (priv->node_path); - if (priv->possible_formats) - g_bytes_unref (priv->possible_formats); - if (priv->properties) - pinos_properties_free (priv->properties); - g_clear_object (&priv->iface); - g_clear_object (&priv->daemon); - - G_OBJECT_CLASS (pinos_port_parent_class)->finalize (object); -} - -static void -pinos_port_class_init (PinosPortClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosPortPrivate)); - - gobject_class->constructed = pinos_port_constructed; - gobject_class->dispose = pinos_port_dispose; - gobject_class->finalize = pinos_port_finalize; - gobject_class->set_property = pinos_port_set_property; - gobject_class->get_property = pinos_port_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_NODE_PATH, - g_param_spec_string ("node-path", - "Node path", - "The Node Path", - 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_NAME, - g_param_spec_string ("name", - "Name", - "The port name", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_DIRECTION, - g_param_spec_enum ("direction", - "Direction", - "The direction of the port", - PINOS_TYPE_DIRECTION, - PINOS_DIRECTION_INVALID, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_POSSIBLE_FORMATS, - g_param_spec_boxed ("possible-formats", - "Possible Formats", - "The possbile formats of the port", - G_TYPE_BYTES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_PROPERTIES, - g_param_spec_boxed ("properties", - "Properties", - "The properties of the port", - PINOS_TYPE_PROPERTIES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - - signals[SIGNAL_FORMAT_REQUEST] = g_signal_new ("format-request", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 0, - G_TYPE_NONE); - signals[SIGNAL_CHANNEL_ADDED] = g_signal_new ("channel-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 1, - PINOS_TYPE_CHANNEL); - signals[SIGNAL_CHANNEL_REMOVED] = g_signal_new ("channel-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 1, - PINOS_TYPE_CHANNEL); - -} - -static void -pinos_port_init (PinosPort * port) -{ - PinosPortPrivate *priv = port->priv = PINOS_PORT_GET_PRIVATE (port); - - priv->iface = pinos_port1_skeleton_new (); - - priv->direction = PINOS_DIRECTION_INVALID; -} - -/** - * pinos_port_new: - * - * - * Returns: a new #PinosPort - */ -PinosPort * -pinos_port_new (PinosDaemon *daemon, - const gchar *node_path, - PinosDirection direction, - const gchar *name, - GBytes *possible_formats, - PinosProperties *props) -{ - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); - g_return_val_if_fail (node_path != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - - return g_object_new (PINOS_TYPE_PORT, - "daemon", daemon, - "node-path", node_path, - "direction", direction, - "name", name, - "possible-formats", possible_formats, - "properties", props, - NULL); -} - -const gchar * -pinos_port_get_object_path (PinosPort *port) -{ - PinosPortPrivate *priv; - - g_return_val_if_fail (PINOS_IS_PORT (port), NULL); - priv = port->priv; - - return priv->object_path; -} - -/** - * pinos_port_get_formats: - * @port: a #PinosPort - * @filter: a #GBytes - * @error: a #GError or %NULL - * - * Get all the currently supported formats for @port and filter the - * results with @filter. - * - * Returns: the list of supported format. If %NULL is returned, @error will - * be set. - */ -GBytes * -pinos_port_get_formats (PinosPort *port, - GBytes *filter, - GError **error) -{ - GstCaps *tmp, *caps, *cfilter; - gchar *str; - PinosPortPrivate *priv; - - g_return_val_if_fail (PINOS_IS_PORT (port), NULL); - priv = port->priv; - - if (filter) { - cfilter = gst_caps_from_string (g_bytes_get_data (filter, NULL)); - if (cfilter == NULL) - goto invalid_filter; - } else { - cfilter = NULL; - } - - g_signal_emit (port, signals[SIGNAL_FORMAT_REQUEST], 0, NULL); - - if (priv->possible_formats) - caps = gst_caps_from_string (g_bytes_get_data (priv->possible_formats, NULL)); - else - caps = gst_caps_new_any (); - - if (caps && cfilter) { - tmp = gst_caps_intersect_full (caps, cfilter, GST_CAPS_INTERSECT_FIRST); - g_clear_pointer (&cfilter, gst_caps_unref); - gst_caps_take (&caps, tmp); - } - if (caps == NULL || gst_caps_is_empty (caps)) - goto no_format; - - str = gst_caps_to_string (caps); - gst_caps_unref (caps); - - return g_bytes_new_take (str, strlen (str) + 1); - -invalid_filter: - { - if (error) - *error = g_error_new (G_IO_ERROR, - G_IO_ERROR_INVALID_ARGUMENT, - "Invalid filter received"); - return NULL; - } -no_format: - { - if (error) - *error = g_error_new (G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "No compatible format found"); - if (cfilter) - gst_caps_unref (cfilter); - if (caps) - gst_caps_unref (caps); - return NULL; - } -} - - -/** - * pinos_port_get_channels: - * @port: a #PinosPort - * - * Get all the channels in @port. - * - * Returns: a #GList of #PinosChannel objects. - */ -GList * -pinos_port_get_channels (PinosPort *port) -{ - PinosPortPrivate *priv; - - g_return_val_if_fail (PINOS_IS_PORT (port), NULL); - priv = port->priv; - - return priv->channels; -} - -static void -handle_remove_channel (PinosChannel *channel, - gpointer user_data) -{ - PinosPort *port = user_data; - - pinos_port_release_channel (port, channel); -} - -/** - * pinos_port_create_channel: - * @port: a #PinosPort - * @client_path: the client path - * @format_filter: a #GBytes - * @props: #PinosProperties - * @prefix: a prefix - * @error: a #GError or %NULL - * - * Create a new #PinosChannel for @port. - * - * Returns: a new #PinosChannel or %NULL, in wich case @error will contain - * more information about the error. - */ -PinosChannel * -pinos_port_create_channel (PinosPort *port, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - GError **error) -{ - PinosPortPrivate *priv; - PinosChannel *channel; - GBytes *possible_formats; - - g_return_val_if_fail (PINOS_IS_PORT (port), NULL); - priv = port->priv; - - possible_formats = pinos_port_get_formats (port, format_filter, error); - if (possible_formats == NULL) - return NULL; - - channel = g_object_new (PINOS_TYPE_CHANNEL, "daemon", priv->daemon, - "client-path", client_path, - "direction", priv->direction, - "port-path", priv->object_path, - "possible-formats", possible_formats, - "properties", props, - NULL); - g_bytes_unref (possible_formats); - - if (channel == NULL) - goto no_channel; - - g_signal_connect (channel, - "remove", - (GCallback) handle_remove_channel, - port); - - priv->channels = g_list_prepend (priv->channels, channel); - - g_signal_emit (port, signals[SIGNAL_CHANNEL_ADDED], 0, channel); - - return g_object_ref (channel); - - /* ERRORS */ -no_channel: - { - if (error) - *error = g_error_new (G_IO_ERROR, - G_IO_ERROR_FAILED, - "Could not create channel"); - return NULL; - } -} - -/** - * pinos_port_release_channel: - * @port: a #PinosPort - * @channel: a #PinosChannel - * - * Release the @channel in @port. - * - * Returns: %TRUE on success. - */ -gboolean -pinos_port_release_channel (PinosPort *port, - PinosChannel *channel) -{ - PinosPortPrivate *priv; - GList *find; - - g_return_val_if_fail (PINOS_IS_PORT (port), FALSE); - g_return_val_if_fail (PINOS_IS_CHANNEL (channel), FALSE); - priv = port->priv; - - find = g_list_find (priv->channels, channel); - if (find == NULL) - return FALSE; - - priv->channels = g_list_delete_link (priv->channels, find); - - g_signal_emit (port, signals[SIGNAL_CHANNEL_REMOVED], 0, channel); - g_object_unref (channel); - - return TRUE; -} diff --git a/pinos/server/port.h b/pinos/server/port.h deleted file mode 100644 index e27fcad18..000000000 --- a/pinos/server/port.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * 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_PORT_H__ -#define __PINOS_PORT_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _PinosPort PinosPort; -typedef struct _PinosPortClass PinosPortClass; -typedef struct _PinosPortPrivate PinosPortPrivate; - -#include -#include -#include - -#define PINOS_TYPE_PORT (pinos_port_get_type ()) -#define PINOS_IS_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_PORT)) -#define PINOS_IS_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_PORT)) -#define PINOS_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_PORT, PinosPortClass)) -#define PINOS_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_PORT, PinosPort)) -#define PINOS_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_PORT, PinosPortClass)) -#define PINOS_PORT_CAST(obj) ((PinosPort*)(obj)) -#define PINOS_PORT_CLASS_CAST(klass) ((PinosPortClass*)(klass)) - -/** - * PinosPort: - * - * Pinos port object class. - */ -struct _PinosPort { - GObject object; - - PinosPortPrivate *priv; -}; - -/** - * PinosPortClass: - * @get_formats: called to get a list of supported formats from the port - * @create_channel: called to create a new channel object - * @release_channel: called to release a channel object - * - * Pinos port object class. - */ -struct _PinosPortClass { - GObjectClass parent_class; -}; - -/* normal GObject stuff */ -GType pinos_port_get_type (void); - -PinosPort * pinos_port_new (PinosDaemon *daemon, - const gchar *node_path, - PinosDirection direction, - const gchar *name, - GBytes *possible_formats, - PinosProperties *props); - -const gchar * pinos_port_get_object_path (PinosPort *port); - -GBytes * pinos_port_get_formats (PinosPort *port, - GBytes *filter, - GError **error); - -PinosChannel * pinos_port_create_channel (PinosPort *port, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - GError **error); -gboolean pinos_port_release_channel (PinosPort *port, - PinosChannel *channel); -GList * pinos_port_get_channels (PinosPort *port); - -G_END_DECLS - -#endif /* __PINOS_PORT_H__ */ diff --git a/pinos/server/server-node.c b/pinos/server/server-node.c new file mode 100644 index 000000000..68e0898c3 --- /dev/null +++ b/pinos/server/server-node.c @@ -0,0 +1,446 @@ +/* Pinos + * Copyright (C) 2015 Wim Taymans + * + * 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 + +#include + +#include "pinos/client/pinos.h" +#include "pinos/client/enumtypes.h" + +#include "pinos/server/server-node.h" +#include "pinos/server/daemon.h" + +#include "pinos/dbus/org-pinos.h" + + +#define PINOS_SERVER_NODE_GET_PRIVATE(node) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((node), PINOS_TYPE_SERVER_NODE, PinosServerNodePrivate)) + +struct _PinosServerNodePrivate +{ + PinosDaemon *daemon; + PinosNode1 *iface; + + gchar *sender; + gchar *object_path; +}; + +G_DEFINE_TYPE (PinosServerNode, pinos_server_node, PINOS_TYPE_NODE); + +enum +{ + PROP_0, + PROP_DAEMON, + PROP_SENDER, + PROP_OBJECT_PATH, +}; + +static gboolean +server_node_set_state (PinosNode *node, + PinosNodeState state) +{ + return FALSE; +} + +static void +server_node_create_port (PinosNode *node, + PinosDirection direction, + const gchar *name, + GBytes *possible_formats, + PinosProperties *props, + GTask *task) +{ + PinosServerNodePrivate *priv = PINOS_SERVER_NODE (node)->priv; + PinosPort *port; + + port = g_object_new (PINOS_TYPE_SERVER_PORT, + "daemon", priv->daemon, + "node", node, + "direction", direction, + "name", name, + "possible-formats", possible_formats, + "properties", props, + NULL); + + g_task_return_pointer (task, port, (GDestroyNotify) g_object_unref); +} + +static void +server_node_remove_port (PinosNode *node, + PinosPort *port) +{ +} + +static void +on_port_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + PinosNode *node = PINOS_NODE (source_object); + GDBusMethodInvocation *invocation = user_data; + PinosPort *port; + const gchar *object_path; + GError *error = NULL; + + port = pinos_node_create_port_finish (node, res, &error); + if (port == NULL) + goto no_port; + + object_path = pinos_server_port_get_object_path (PINOS_SERVER_PORT (port)); + g_debug ("node %p: add port %p, %s", node, port, object_path); + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(o)", object_path)); + + return; + +no_port: + { + g_debug ("server-node %p: could create port", node); + g_dbus_method_invocation_return_dbus_error (invocation, + "org.pinos.Error", "can't create port"); + return; + } +} + + +static gboolean +handle_create_port (PinosNode1 *interface, + GDBusMethodInvocation *invocation, + PinosDirection arg_direction, + const gchar *arg_name, + GVariant *arg_properties, + const gchar *arg_possible_formats, + gpointer user_data) +{ + PinosNode *node = user_data; + PinosServerNodePrivate *priv = PINOS_SERVER_NODE (node)->priv; + const gchar *sender; + PinosProperties *props; + GBytes *formats; + + sender = g_dbus_method_invocation_get_sender (invocation); + if (g_strcmp0 (priv->sender, sender) != 0) + goto not_allowed; + + formats = g_bytes_new (arg_possible_formats, strlen (arg_possible_formats) + 1); + props = pinos_properties_from_variant (arg_properties); + + pinos_node_create_port (node, + arg_direction, + arg_name, + formats, + props, + NULL, + on_port_created, + invocation); + + g_bytes_unref (formats); + pinos_properties_free (props); + + return TRUE; + + /* ERRORS */ +not_allowed: + { + g_debug ("sender %s is not owner of node with sender %s", sender, priv->sender); + g_dbus_method_invocation_return_dbus_error (invocation, + "org.pinos.Error", "not node owner"); + return TRUE; + } +} + +static gboolean +handle_remove (PinosNode1 *interface, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + PinosNode *node = user_data; + + g_debug ("server-node %p: remove", node); + pinos_node_remove (node); + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); + return TRUE; +} + +static void +pinos_server_node_get_property (GObject *_object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + PinosServerNode *node = PINOS_SERVER_NODE (_object); + PinosServerNodePrivate *priv = node->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; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec); + break; + } +} + +static void +pinos_server_node_set_property (GObject *_object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + PinosServerNode *node = PINOS_SERVER_NODE (_object); + PinosServerNodePrivate *priv = node->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); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec); + break; + } +} + +static void +node_register_object (PinosServerNode *node) +{ + PinosServerNodePrivate *priv = node->priv; + PinosDaemon *daemon = priv->daemon; + PinosObjectSkeleton *skel; + + skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_NODE); + + pinos_object_skeleton_set_node1 (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 ("server-node %p: register object %s", node, priv->object_path); + pinos_daemon_add_node (daemon, node); + + return; +} + +static void +node_unregister_object (PinosServerNode *node) +{ + PinosServerNodePrivate *priv = node->priv; + + g_debug ("server-node %p: unregister object %s", node, priv->object_path); + pinos_daemon_unexport (priv->daemon, priv->object_path); + pinos_daemon_remove_node (priv->daemon, node); +} + +static void +pinos_server_node_constructed (GObject * obj) +{ + PinosServerNode *node = PINOS_SERVER_NODE (obj); + + g_debug ("server-node %p: constructed", node); + node_register_object (node); + + G_OBJECT_CLASS (pinos_server_node_parent_class)->constructed (obj); +} + +static void +pinos_server_node_dispose (GObject * obj) +{ + PinosServerNode *node = PINOS_SERVER_NODE (obj); + + g_debug ("server-node %p: dispose", node); + node_unregister_object (node); + + G_OBJECT_CLASS (pinos_server_node_parent_class)->dispose (obj); +} + +static void +pinos_server_node_finalize (GObject * obj) +{ + PinosServerNode *node = PINOS_SERVER_NODE (obj); + PinosServerNodePrivate *priv = node->priv; + + g_debug ("server-node %p: finalize", node); + g_clear_object (&priv->daemon); + g_clear_object (&priv->iface); + + G_OBJECT_CLASS (pinos_server_node_parent_class)->finalize (obj); +} + +static void +pinos_server_node_class_init (PinosServerNodeClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + PinosNodeClass *node_class = PINOS_NODE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (PinosServerNodePrivate)); + + gobject_class->constructed = pinos_server_node_constructed; + gobject_class->dispose = pinos_server_node_dispose; + gobject_class->finalize = pinos_server_node_finalize; + gobject_class->set_property = pinos_server_node_set_property; + gobject_class->get_property = pinos_server_node_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)); + node_class->set_state = server_node_set_state; + node_class->create_port = server_node_create_port; + node_class->remove_port = server_node_remove_port; +} + +static void +pinos_server_node_init (PinosServerNode * node) +{ + PinosServerNodePrivate *priv = node->priv = PINOS_SERVER_NODE_GET_PRIVATE (node); + + g_debug ("server-node %p: new", node); + priv->iface = pinos_node1_skeleton_new (); + g_signal_connect (priv->iface, "handle-create-port", + (GCallback) handle_create_port, + node); + g_signal_connect (priv->iface, "handle-remove", + (GCallback) handle_remove, + node); + pinos_node1_set_state (priv->iface, PINOS_NODE_STATE_SUSPENDED); +} + +/** + * pinos_server_node_new: + * @daemon: a #PinosDaemon + * @sender: the path of the owner + * @name: a name + * @properties: extra properties + * + * Create a new #PinosServerNode. + * + * Returns: a new #PinosServerNode + */ +PinosNode * +pinos_server_node_new (PinosDaemon *daemon, + const gchar *sender, + const gchar *name, + PinosProperties *properties) +{ + g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); + + return g_object_new (PINOS_TYPE_SERVER_NODE, + "daemon", daemon, + "sender", sender, + "name", name, + "properties", properties, + NULL); +} + +/** + * pinos_server_node_get_daemon: + * @node: a #PinosServerNode + * + * Get the daemon of @node. + * + * Returns: the daemon of @node. + */ +PinosDaemon * +pinos_server_node_get_daemon (PinosServerNode *node) +{ + PinosServerNodePrivate *priv; + + g_return_val_if_fail (PINOS_IS_SERVER_NODE (node), NULL); + priv = node->priv; + + return priv->daemon; +} + +/** + * pinos_server_node_get_sender: + * @node: a #PinosServerNode + * + * Get the owner path of @node. + * + * Returns: the owner path of @node. + */ +const gchar * +pinos_server_node_get_sender (PinosServerNode *node) +{ + PinosServerNodePrivate *priv; + + g_return_val_if_fail (PINOS_IS_SERVER_NODE (node), NULL); + priv = node->priv; + + return priv->sender; +} +/** + * pinos_server_node_get_object_path: + * @node: a #PinosServerNode + * + * Get the object path of @node. + * + * Returns: the object path of @node. + */ +const gchar * +pinos_server_node_get_object_path (PinosServerNode *node) +{ + PinosServerNodePrivate *priv; + + g_return_val_if_fail (PINOS_IS_SERVER_NODE (node), NULL); + priv = node->priv; + + return priv->object_path; +} diff --git a/pinos/server/server-node.h b/pinos/server/server-node.h new file mode 100644 index 000000000..0f46cd884 --- /dev/null +++ b/pinos/server/server-node.h @@ -0,0 +1,79 @@ +/* Pinos + * Copyright (C) 2015 Wim Taymans + * + * 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_SERVER_NODE_H__ +#define __PINOS_SERVER_NODE_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _PinosServerNode PinosServerNode; +typedef struct _PinosServerNodeClass PinosServerNodeClass; +typedef struct _PinosServerNodePrivate PinosServerNodePrivate; + +#include +#include +#include + +#define PINOS_TYPE_SERVER_NODE (pinos_server_node_get_type ()) +#define PINOS_IS_SERVER_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_SERVER_NODE)) +#define PINOS_IS_SERVER_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_SERVER_NODE)) +#define PINOS_SERVER_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_SERVER_NODE, PinosServerNodeClass)) +#define PINOS_SERVER_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_SERVER_NODE, PinosServerNode)) +#define PINOS_SERVER_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_SERVER_NODE, PinosServerNodeClass)) +#define PINOS_SERVER_NODE_CAST(obj) ((PinosServerNode*)(obj)) +#define PINOS_SERVER_NODE_CLASS_CAST(klass) ((PinosServerNodeClass*)(klass)) + +/** + * PinosServerServerNode: + * + * Pinos node class. + */ +struct _PinosServerNode { + PinosNode object; + + PinosServerNodePrivate *priv; +}; + +/** + * PinosServerNodeClass: + * @set_state: called to change the current state of the node + * + * Pinos node class. + */ +struct _PinosServerNodeClass { + PinosNodeClass parent_class; +}; + +/* normal GObject stuff */ +GType pinos_server_node_get_type (void); + +PinosNode * pinos_server_node_new (PinosDaemon *daemon, + const gchar *sender, + const gchar *name, + PinosProperties *properties); + +PinosDaemon * pinos_server_node_get_daemon (PinosServerNode *node); +const gchar * pinos_server_node_get_sender (PinosServerNode *node); +const gchar * pinos_server_node_get_object_path (PinosServerNode *node); + +G_END_DECLS + +#endif /* __PINOS_SERVER_NODE_H__ */ diff --git a/pinos/server/server-port.c b/pinos/server/server-port.c new file mode 100644 index 000000000..4c021562b --- /dev/null +++ b/pinos/server/server-port.c @@ -0,0 +1,235 @@ +/* Pinos + * Copyright (C) 2015 Wim Taymans + * + * 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 + +#include +#include + +#include "pinos/client/pinos.h" +#include "pinos/client/enumtypes.h" + +#include "pinos/server/server-port.h" +#include "pinos/server/server-node.h" + +#include "pinos/dbus/org-pinos.h" + +#define PINOS_SERVER_PORT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SERVER_PORT, PinosServerPortPrivate)) + +struct _PinosServerPortPrivate +{ + PinosDaemon *daemon; + PinosPort1 *iface; + gchar *object_path; +}; + +G_DEFINE_TYPE (PinosServerPort, pinos_server_port, PINOS_TYPE_PORT); + +enum +{ + PROP_0, + PROP_DAEMON, + PROP_OBJECT_PATH, +}; + +static gboolean +handle_remove (PinosPort1 *interface, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + PinosPort *port = user_data; + + g_debug ("server-port %p: remove", port); + pinos_port_remove (port); + + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("()")); + return TRUE; +} + +static void +pinos_server_port_get_property (GObject *_object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + PinosServerPort *port = PINOS_SERVER_PORT (_object); + PinosServerPortPrivate *priv = port->priv; + + switch (prop_id) { + case PROP_DAEMON: + g_value_set_object (value, priv->daemon); + break; + + case PROP_OBJECT_PATH: + g_value_set_string (value, priv->object_path); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (port, prop_id, pspec); + break; + } +} + +static void +pinos_server_port_set_property (GObject *_object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + PinosServerPort *port = PINOS_SERVER_PORT (_object); + PinosServerPortPrivate *priv = port->priv; + + switch (prop_id) { + case PROP_DAEMON: + priv->daemon = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (port, prop_id, pspec); + break; + } +} + +static void +port_register_object (PinosServerPort *port) +{ + PinosServerPortPrivate *priv = port->priv; + PinosObjectSkeleton *skel; + gchar *name; + PinosNode *node; + + node = pinos_port_get_node (PINOS_PORT (port)); + + name = g_strdup_printf ("%s/port", pinos_server_node_get_object_path (PINOS_SERVER_NODE (node))); + skel = pinos_object_skeleton_new (name); + g_free (name); + + pinos_object_skeleton_set_port1 (skel, priv->iface); + + g_free (priv->object_path); + priv->object_path = pinos_daemon_export_uniquely (priv->daemon, + G_DBUS_OBJECT_SKELETON (skel)); + g_object_unref (skel); + g_debug ("server-port %p: register object %s", port, priv->object_path); + + return; +} + +static void +port_unregister_object (PinosServerPort *port) +{ + PinosServerPortPrivate *priv = port->priv; + + g_debug ("server-port %p: unregister object %s", port, priv->object_path); + pinos_daemon_unexport (priv->daemon, priv->object_path); +} + +static void +pinos_server_port_constructed (GObject * object) +{ + PinosServerPort *port = PINOS_SERVER_PORT (object); + + g_debug ("server-port %p: constructed", port); + port_register_object (port); + + G_OBJECT_CLASS (pinos_server_port_parent_class)->constructed (object); +} + +static void +pinos_server_port_dispose (GObject * object) +{ + PinosServerPort *port = PINOS_SERVER_PORT (object); + + g_debug ("server-port %p: dispose", port); + port_unregister_object (port); + + G_OBJECT_CLASS (pinos_server_port_parent_class)->dispose (object); +} + +static void +pinos_server_port_finalize (GObject * object) +{ + PinosServerPort *port = PINOS_SERVER_PORT (object); + PinosServerPortPrivate *priv = port->priv; + + g_debug ("server-port %p: finalize", port); + g_free (priv->object_path); + g_clear_object (&priv->iface); + g_clear_object (&priv->daemon); + + G_OBJECT_CLASS (pinos_server_port_parent_class)->finalize (object); +} + +static void +pinos_server_port_class_init (PinosServerPortClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (PinosServerPortPrivate)); + + gobject_class->constructed = pinos_server_port_constructed; + gobject_class->dispose = pinos_server_port_dispose; + gobject_class->finalize = pinos_server_port_finalize; + gobject_class->set_property = pinos_server_port_set_property; + gobject_class->get_property = pinos_server_port_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_OBJECT_PATH, + g_param_spec_string ("object-path", + "Object Path", + "The object path", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +static void +pinos_server_port_init (PinosServerPort * port) +{ + PinosServerPortPrivate *priv = port->priv = PINOS_SERVER_PORT_GET_PRIVATE (port); + + g_debug ("server-port %p: new", port); + priv->iface = pinos_port1_skeleton_new (); + g_signal_connect (priv->iface, "handle-remove", + (GCallback) handle_remove, + port); + +} + +const gchar * +pinos_server_port_get_object_path (PinosServerPort *port) +{ + PinosServerPortPrivate *priv; + + g_return_val_if_fail (PINOS_IS_SERVER_PORT (port), NULL); + priv = port->priv; + + return priv->object_path; +} diff --git a/pinos/server/server-port.h b/pinos/server/server-port.h new file mode 100644 index 000000000..e1bed7052 --- /dev/null +++ b/pinos/server/server-port.h @@ -0,0 +1,71 @@ +/* Pinos + * Copyright (C) 2015 Wim Taymans + * + * 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_SERVER_PORT_H__ +#define __PINOS_SERVER_PORT_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _PinosServerPort PinosServerPort; +typedef struct _PinosServerPortClass PinosServerPortClass; +typedef struct _PinosServerPortPrivate PinosServerPortPrivate; + +#include +#include +#include + +#define PINOS_TYPE_SERVER_PORT (pinos_server_port_get_type ()) +#define PINOS_IS_SERVER_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_SERVER_PORT)) +#define PINOS_IS_SERVER_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_SERVER_PORT)) +#define PINOS_SERVER_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_SERVER_PORT, PinosServerPortClass)) +#define PINOS_SERVER_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_SERVER_PORT, PinosServerPort)) +#define PINOS_SERVER_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_SERVER_PORT, PinosServerPortClass)) +#define PINOS_SERVER_PORT_CAST(obj) ((PinosServerPort*)(obj)) +#define PINOS_SERVER_PORT_CLASS_CAST(klass)((PinosServerPortClass*)(klass)) + +/** + * PinosServerPort: + * + * Pinos port object class. + */ +struct _PinosServerPort { + PinosPort object; + + PinosServerPortPrivate *priv; +}; + +/** + * PinosServerPortClass: + * + * Pinos port object class. + */ +struct _PinosServerPortClass { + PinosPortClass parent_class; +}; + +/* normal GObject stuff */ +GType pinos_server_port_get_type (void); + +const gchar * pinos_server_port_get_object_path (PinosServerPort *port); + +G_END_DECLS + +#endif /* __PINOS_SERVER_PORT_H__ */ diff --git a/pinos/server/source.c b/pinos/server/source.c deleted file mode 100644 index bc79d02ab..000000000 --- a/pinos/server/source.c +++ /dev/null @@ -1,646 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * 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 - -#include "pinos/client/pinos.h" -#include "pinos/client/enumtypes.h" - -#include "pinos/server/source.h" -#include "pinos/server/node.h" - -#include "pinos/dbus/org-pinos.h" - - -#define PINOS_SOURCE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SOURCE, PinosSourcePrivate)) - -struct _PinosSourcePrivate -{ - PinosNode *node; - PinosSource1 *iface; - - gchar *name; - PinosProperties *properties; - - PinosSourceState state; - GError *error; - guint idle_timeout; - - GList *channels; -}; - -G_DEFINE_ABSTRACT_TYPE (PinosSource, pinos_source, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_NODE, - PROP_NAME, - PROP_STATE, - PROP_PROPERTIES -}; - -static void -pinos_source_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosSource *source = PINOS_SOURCE (_object); - PinosSourcePrivate *priv = source->priv; - - switch (prop_id) { - case PROP_NODE: - g_value_set_object (value, priv->node); - break; - - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - - case PROP_STATE: - g_value_set_enum (value, priv->state); - break; - - case PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (source, prop_id, pspec); - break; - } -} - -static void -pinos_source_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosSource *source = PINOS_SOURCE (_object); - PinosSourcePrivate *priv = source->priv; - - switch (prop_id) { - case PROP_NODE: - priv->node = g_value_dup_object (value); - break; - - case PROP_NAME: - g_free (priv->name); - priv->name = g_value_dup_string (value); - break; - - case PROP_PROPERTIES: - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = g_value_dup_boxed (value); - if (priv->iface) - g_object_set (priv->iface, - "properties", priv->properties ? - pinos_properties_to_variant (priv->properties) : NULL, - NULL); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (source, prop_id, pspec); - break; - } -} - -static void -source_register_object (PinosSource *source) -{ - PinosSourcePrivate *priv = source->priv; - GBytes *formats; - GVariant *variant; - - formats = pinos_source_get_formats (source, NULL, NULL); - - if (priv->properties) - variant = pinos_properties_to_variant (priv->properties); - else - variant = NULL; - - priv->iface = pinos_source1_skeleton_new (); - g_object_set (priv->iface, "name", priv->name, - "state", priv->state, - "properties", variant, - "possible-formats", g_bytes_get_data (formats, NULL), - NULL); - g_bytes_unref (formats); - - pinos_node_set_source (priv->node, source, G_OBJECT (priv->iface)); - - return; -} - -static void -source_unregister_object (PinosSource *source) -{ - PinosSourcePrivate *priv = source->priv; - - pinos_node_set_source (priv->node, NULL, NULL); - g_clear_object (&priv->iface); -} - -static void -pinos_source_constructed (GObject * object) -{ - PinosSource *source = PINOS_SOURCE (object); - - source_register_object (source); - - G_OBJECT_CLASS (pinos_source_parent_class)->constructed (object); -} - -static void -do_remove_channel (PinosChannel *channel, - gpointer user_data) -{ - pinos_channel_remove (channel); -} - -static void -pinos_source_dispose (GObject * object) -{ - PinosSource *source = PINOS_SOURCE (object); - PinosSourcePrivate *priv = source->priv; - - g_list_foreach (priv->channels, (GFunc) do_remove_channel, source); - source_unregister_object (source); - - G_OBJECT_CLASS (pinos_source_parent_class)->dispose (object); -} - -static void -pinos_source_finalize (GObject * object) -{ - PinosSource *source = PINOS_SOURCE (object); - PinosSourcePrivate *priv = source->priv; - - g_free (priv->name); - if (priv->properties) - pinos_properties_free (priv->properties); - - G_OBJECT_CLASS (pinos_source_parent_class)->finalize (object); -} - -static gboolean -default_set_state (PinosSource *source, - PinosSourceState state) -{ - pinos_source_update_state (source, state); - return TRUE; -} - -static void -handle_remove_channel (PinosChannel *channel, - gpointer user_data) -{ - PinosSource *source = user_data; - - pinos_source_release_channel (source, channel); -} - -static PinosChannel * -default_create_channel (PinosSource *source, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - const gchar *prefix, - GError **error) -{ - PinosSourcePrivate *priv = source->priv; - PinosChannel *channel; - GBytes *possible_formats; - - possible_formats = pinos_source_get_formats (source, format_filter, error); - if (possible_formats == NULL) - return NULL; - - channel = g_object_new (PINOS_TYPE_CHANNEL, "daemon", pinos_node_get_daemon (priv->node), - "object-path", prefix, - "client-path", client_path, - "owner-path", pinos_node_get_object_path (priv->node), - "possible-formats", possible_formats, - "properties", props, - NULL); - g_bytes_unref (possible_formats); - - if (channel == NULL) - goto no_channel; - - g_signal_connect (channel, - "remove", - (GCallback) handle_remove_channel, - source); - - priv->channels = g_list_prepend (priv->channels, channel); - - return g_object_ref (channel); - - /* ERRORS */ -no_channel: - { - if (error) - *error = g_error_new (G_IO_ERROR, - G_IO_ERROR_FAILED, - "Could not create channel"); - return NULL; - } -} - -static gboolean -default_release_channel (PinosSource *source, - PinosChannel *channel) -{ - PinosSourcePrivate *priv = source->priv; - GList *find; - - find = g_list_find (priv->channels, channel); - if (find == NULL) - return FALSE; - - priv->channels = g_list_delete_link (priv->channels, find); - g_object_unref (channel); - - return TRUE; -} - -static void -pinos_source_class_init (PinosSourceClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosSourcePrivate)); - - gobject_class->constructed = pinos_source_constructed; - gobject_class->dispose = pinos_source_dispose; - gobject_class->finalize = pinos_source_finalize; - gobject_class->set_property = pinos_source_set_property; - gobject_class->get_property = pinos_source_get_property; - - g_object_class_install_property (gobject_class, - PROP_NODE, - g_param_spec_object ("node", - "Node", - "The Node", - PINOS_TYPE_NODE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_NAME, - g_param_spec_string ("name", - "Name", - "The source name", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_STATE, - g_param_spec_enum ("state", - "State", - "The state of the source", - PINOS_TYPE_SOURCE_STATE, - PINOS_SOURCE_STATE_SUSPENDED, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_PROPERTIES, - g_param_spec_boxed ("properties", - "Properties", - "The properties of the source", - PINOS_TYPE_PROPERTIES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - - klass->set_state = default_set_state; - klass->create_channel = default_create_channel; - klass->release_channel = default_release_channel; -} - -static void -pinos_source_init (PinosSource * source) -{ - PinosSourcePrivate *priv = source->priv = PINOS_SOURCE_GET_PRIVATE (source); - - priv->state = PINOS_SOURCE_STATE_SUSPENDED; -} - -/** - * pinos_source_get_formats: - * @source: a #PinosSource - * @filter: a #GBytes - * @error: a #GError or %NULL - * - * Get all the currently supported formats for @source and filter the - * results with @filter. - * - * Returns: the list of supported format. If %NULL is returned, @error will - * be set. - */ -GBytes * -pinos_source_get_formats (PinosSource *source, - GBytes *filter, - GError **error) -{ - PinosSourceClass *klass; - GBytes *res; - - g_return_val_if_fail (PINOS_IS_SOURCE (source), NULL); - - klass = PINOS_SOURCE_GET_CLASS (source); - - if (klass->get_formats) - res = klass->get_formats (source, filter, error); - else { - res = NULL; - if (error) - *error = g_error_new (G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "Format query is not supported"); - } - return res; -} - -static void -remove_idle_timeout (PinosSource *source) -{ - PinosSourcePrivate *priv = source->priv; - - if (priv->idle_timeout) { - g_source_remove (priv->idle_timeout); - priv->idle_timeout = 0; - } -} - -/** - * pinos_source_set_state: - * @source: a #PinosSource - * @state: a #PinosSourceState - * - * Set the state of @source to @state. - * - * Returns: %TRUE on success. - */ -gboolean -pinos_source_set_state (PinosSource *source, - PinosSourceState state) -{ - PinosSourceClass *klass; - gboolean res; - - g_return_val_if_fail (PINOS_IS_SOURCE (source), FALSE); - - klass = PINOS_SOURCE_GET_CLASS (source); - - remove_idle_timeout (source); - - if (klass->set_state) - res = klass->set_state (source, state); - else - res = FALSE; - - return res; -} - -/** - * pinos_source_update_state: - * @source: a #PinosSource - * @state: a #PinosSourceState - * - * Update the state of a source. This method is used from - * inside @source itself. - */ -void -pinos_source_update_state (PinosSource *source, - PinosSourceState state) -{ - PinosSourcePrivate *priv; - - g_return_if_fail (PINOS_IS_SOURCE (source)); - priv = source->priv; - - if (priv->state != state) { - priv->state = state; - pinos_source1_set_state (priv->iface, state); - g_object_notify (G_OBJECT (source), "state"); - } -} - -/** - * pinos_source_report_error: - * @source: a #PinosSource - * @error: a #GError - * - * Report an error from within @source. - */ -void -pinos_source_report_error (PinosSource *source, - GError *error) -{ - PinosSourcePrivate *priv; - - g_return_if_fail (PINOS_IS_SOURCE (source)); - priv = source->priv; - - g_clear_error (&priv->error); - remove_idle_timeout (source); - priv->error = error; - priv->state = PINOS_SOURCE_STATE_ERROR; - g_debug ("got error state %s", error->message); - pinos_source1_set_state (priv->iface, priv->state); - g_object_notify (G_OBJECT (source), "state"); -} - -static gboolean -idle_timeout (PinosSource *source) -{ - PinosSourcePrivate *priv = source->priv; - - priv->idle_timeout = 0; - pinos_source_set_state (source, PINOS_SOURCE_STATE_SUSPENDED); - - return G_SOURCE_REMOVE; -} - -/** - * pinos_source_report_idle: - * @source: a #PinosSource - * - * Mark @source as being idle. This will start a timeout that will - * set the source to SUSPENDED. - */ -void -pinos_source_report_idle (PinosSource *source) -{ - PinosSourcePrivate *priv; - - g_return_if_fail (PINOS_IS_SOURCE (source)); - priv = source->priv; - - pinos_source_set_state (source, PINOS_SOURCE_STATE_IDLE); - - priv->idle_timeout = g_timeout_add_seconds (3, - (GSourceFunc) idle_timeout, - source); -} - -/** - * pinos_source_report_busy: - * @source: a #PinosSource - * - * Mark @source as being busy. This will set the state of the source - * to the RUNNING state. - */ -void -pinos_source_report_busy (PinosSource *source) -{ - g_return_if_fail (PINOS_IS_SOURCE (source)); - - pinos_source_set_state (source, PINOS_SOURCE_STATE_RUNNING); -} - -/** - * pinos_source_update_possible_formats: - * @source: a #PinosSource - * @formats: a #GBytes - * - * Update the possible formats in @source to @formats. This function also - * updates the possible formats of the channels. - */ -void -pinos_source_update_possible_formats (PinosSource *source, GBytes *formats) -{ - PinosSourcePrivate *priv; - GList *walk; - - g_return_if_fail (PINOS_IS_SOURCE (source)); - priv = source->priv; - - if (priv->iface) - g_object_set (priv->iface, "possible-formats", - g_bytes_get_data (formats, NULL), - NULL); - - for (walk = priv->channels; walk; walk = g_list_next (walk)) - g_object_set (walk->data, "possible-formats", formats, NULL); -} - -/** - * pinos_source_update_format: - * @source: a #PinosSource - * @format: a #GBytes - * - * Update the current format in @source to @format. This function also - * updates the current format of the channels. - */ -void -pinos_source_update_format (PinosSource *source, GBytes *format) -{ - PinosSourcePrivate *priv; - GList *walk; - - g_return_if_fail (PINOS_IS_SOURCE (source)); - priv = source->priv; - - for (walk = priv->channels; walk; walk = g_list_next (walk)) - g_object_set (walk->data, "format", format, NULL); -} - -/** - * pinos_source_create_channel: - * @source: a #PinosSource - * @client_path: the client path - * @format_filter: a #GBytes - * @props: #PinosProperties - * @prefix: a prefix - * @error: a #GError or %NULL - * - * Create a new #PinosChannel for @source. - * - * Returns: a new #PinosChannel or %NULL, in wich case @error will contain - * more information about the error. - */ -PinosChannel * -pinos_source_create_channel (PinosSource *source, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - const gchar *prefix, - GError **error) -{ - PinosSourceClass *klass; - PinosChannel *res; - - g_return_val_if_fail (PINOS_IS_SOURCE (source), NULL); - - klass = PINOS_SOURCE_GET_CLASS (source); - - if (klass->create_channel) { - res = klass->create_channel (source, client_path, format_filter, props, prefix, error); - } else { - if (error) { - *error = g_error_new (G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "CreateChannel not implemented"); - } - res = NULL; - } - - return res; -} - -/** - * pinos_source_release_channel: - * @source: a #PinosSource - * @channel: a #PinosChannel - * - * Release the @channel in @source. - * - * Returns: %TRUE on success. - */ -gboolean -pinos_source_release_channel (PinosSource *source, - PinosChannel *channel) -{ - PinosSourceClass *klass; - gboolean res; - - g_return_val_if_fail (PINOS_IS_SOURCE (source), FALSE); - g_return_val_if_fail (PINOS_IS_CHANNEL (channel), FALSE); - - klass = PINOS_SOURCE_GET_CLASS (source); - - if (klass->release_channel) - res = klass->release_channel (source, channel); - else - res = FALSE; - - return res; -} diff --git a/pinos/server/source.h b/pinos/server/source.h deleted file mode 100644 index 25c149bbf..000000000 --- a/pinos/server/source.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * 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_SOURCE_H__ -#define __PINOS_SOURCE_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _PinosSource PinosSource; -typedef struct _PinosSourceClass PinosSourceClass; -typedef struct _PinosSourcePrivate PinosSourcePrivate; - -#include -#include - -#define PINOS_TYPE_SOURCE (pinos_source_get_type ()) -#define PINOS_IS_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_SOURCE)) -#define PINOS_IS_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_SOURCE)) -#define PINOS_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_SOURCE, PinosSourceClass)) -#define PINOS_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_SOURCE, PinosSource)) -#define PINOS_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_SOURCE, PinosSourceClass)) -#define PINOS_SOURCE_CAST(obj) ((PinosSource*)(obj)) -#define PINOS_SOURCE_CLASS_CAST(klass) ((PinosSourceClass*)(klass)) - -/** - * PinosSource: - * - * Pinos source object class. - */ -struct _PinosSource { - GObject object; - - PinosSourcePrivate *priv; -}; - -/** - * PinosSourceClass: - * @get_formats: called to get a list of supported formats from the source - * @set_state: called to change the current state of the source - * @create_channel: called to create a new channel object - * @release_channel: called to release a channel object - * - * Pinos source object class. - */ -struct _PinosSourceClass { - GObjectClass parent_class; - - GBytes * (*get_formats) (PinosSource *source, - GBytes *filter, - GError **error); - - gboolean (*set_state) (PinosSource *source, PinosSourceState); - - PinosChannel * (*create_channel) (PinosSource *source, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - const gchar *prefix, - GError **error); - gboolean (*release_channel) (PinosSource *source, - PinosChannel *channel); -}; - -/* normal GObject stuff */ -GType pinos_source_get_type (void); - -GBytes * pinos_source_get_formats (PinosSource *source, - GBytes *filter, - GError **error); - -gboolean pinos_source_set_state (PinosSource *source, PinosSourceState state); -void pinos_source_update_state (PinosSource *source, PinosSourceState state); -void pinos_source_report_error (PinosSource *source, GError *error); -void pinos_source_report_idle (PinosSource *source); -void pinos_source_report_busy (PinosSource *source); - -void pinos_source_update_possible_formats (PinosSource *source, GBytes *formats); -void pinos_source_update_format (PinosSource *source, GBytes *format); - -PinosChannel * pinos_source_create_channel (PinosSource *source, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - const gchar *prefix, - GError **error); -gboolean pinos_source_release_channel (PinosSource *source, - PinosChannel *channel); - -G_END_DECLS - -#endif /* __PINOS_SOURCE_H__ */ diff --git a/pinos/server/upload-node.c b/pinos/server/upload-node.c index 6e4d96e97..fd4df1a5c 100644 --- a/pinos/server/upload-node.c +++ b/pinos/server/upload-node.c @@ -38,11 +38,9 @@ struct _PinosUploadNodePrivate GBytes *possible_formats; PinosPort *input, *output; - - PinosChannel *channel; }; -G_DEFINE_TYPE (PinosUploadNode, pinos_upload_node, PINOS_TYPE_NODE); +G_DEFINE_TYPE (PinosUploadNode, pinos_upload_node, PINOS_TYPE_SERVER_NODE); enum { @@ -94,18 +92,12 @@ upload_node_set_property (GObject *_object, } } -static void -update_channel_format (PinosChannel *channel, GBytes *format) -{ - g_object_set (channel, "format", format, NULL); -} - static gboolean bus_handler (GstBus *bus, GstMessage *message, gpointer user_data) { - PinosNode *node = user_data; + PinosServerNode *node = user_data; PinosUploadNodePrivate *priv = PINOS_UPLOAD_NODE (node)->priv; switch (GST_MESSAGE_TYPE (message)) { @@ -118,7 +110,7 @@ bus_handler (GstBus *bus, g_warning ("got error %s (%s)\n", error->message, debug); g_free (debug); - pinos_node_report_error (node, error); + pinos_node_report_error (PINOS_NODE (node), error); gst_element_set_state (priv->pipeline, GST_STATE_NULL); break; } @@ -127,17 +119,9 @@ bus_handler (GstBus *bus, if (gst_message_has_name (message, "PinosPayloaderFormatChange")) { const GstStructure *str = gst_message_get_structure (message); GstCaps *caps; - GBytes *format; - gchar *caps_str; gst_structure_get (str, "format", GST_TYPE_CAPS, &caps, NULL); gst_caps_replace (&priv->format, caps); - caps_str = gst_caps_to_string (caps); - - format = g_bytes_new_take (caps_str, strlen (caps_str) + 1); - g_list_foreach (pinos_port_get_channels (priv->output), (GFunc) update_channel_format, format); - g_list_foreach (pinos_port_get_channels (priv->input), (GFunc) update_channel_format, format); - g_bytes_unref (format); } break; } @@ -172,8 +156,8 @@ setup_pipeline (PinosUploadNode *node) } static gboolean -node_set_state (PinosNode *node, - PinosNodeState state) +node_set_state (PinosNode *node, + PinosNodeState state) { PinosUploadNodePrivate *priv = PINOS_UPLOAD_NODE (node)->priv; @@ -202,56 +186,6 @@ node_set_state (PinosNode *node, return TRUE; } -static void -on_socket_notify (GObject *gobject, - GParamSpec *pspec, - gpointer user_data) -{ - PinosUploadNode *node = user_data; - PinosUploadNodePrivate *priv = node->priv; - GSocket *socket; - guint num_handles; - - g_object_get (gobject, "socket", &socket, NULL); - - g_debug ("upload-node %p: output socket notify %p", node, socket); - - if (socket == NULL) { - GSocket *prev_socket = g_object_steal_data (gobject, "last-socket"); - if (prev_socket) { - g_signal_emit_by_name (priv->sink, "remove", prev_socket); - g_object_unref (prev_socket); - } - } else { - g_signal_emit_by_name (priv->sink, "add", socket); - g_object_set_data_full (gobject, "last-socket", socket, g_object_unref); - } - - g_object_get (priv->sink, "num-handles", &num_handles, NULL); - if (num_handles > 0 && socket) { - GBytes *format; - - /* suggest what we provide */ - g_object_get (priv->channel, "format", &format, NULL); - g_object_set (gobject, "format", format, NULL); - g_bytes_unref (format); - } -} - -static void -on_channel_added (PinosPort *port, PinosChannel *channel, PinosNode *node) -{ - g_signal_connect (channel, "notify::socket", (GCallback) on_socket_notify, node); - - g_debug ("upload-node %p: create channel %p", node, channel); -} - -static void -on_channel_removed (PinosPort *port, PinosChannel *channel, PinosNode *node) -{ - g_debug ("upload-node %p: release channel %p", node, channel); -} - static void upload_node_dispose (GObject * object) { @@ -272,7 +206,6 @@ upload_node_finalize (GObject * object) g_debug ("upload-node %p: finalize", object); - g_clear_object (&priv->channel); g_clear_object (&priv->sink); g_clear_object (&priv->src); g_clear_object (&priv->pipeline); @@ -284,136 +217,54 @@ upload_node_finalize (GObject * object) G_OBJECT_CLASS (pinos_upload_node_parent_class)->finalize (object); } - static void -on_input_socket_notify (GObject *gobject, - GParamSpec *pspec, - gpointer user_data) -{ - PinosUploadNode *node = user_data; - PinosUploadNodePrivate *priv = node->priv; - GSocket *socket; - GBytes *requested_format; - GstCaps *caps; - - g_object_get (gobject, "socket", &socket, NULL); - g_debug ("upload-node %p: input socket notify %p", node, socket); - - if (socket) { - /* requested format is final format */ - g_object_get (gobject, "requested-format", &requested_format, NULL); - g_assert (requested_format != NULL); - g_object_set (gobject, "format", requested_format, NULL); - - /* and set as the current format */ - caps = gst_caps_from_string (g_bytes_get_data (requested_format, NULL)); - g_assert (caps != NULL); - gst_caps_take (&priv->format, caps); - g_bytes_unref (requested_format); - } else { - gst_caps_replace (&priv->format, NULL); - } - g_object_set (priv->src, "socket", socket, NULL); - - if (socket) { - g_debug ("upload-node %p: set pipeline to PLAYING", node); - gst_element_set_state (priv->pipeline, GST_STATE_PLAYING); - g_object_unref (socket); - } else { - g_debug ("upload-node %p: set pipeline to READY", node); - gst_element_set_state (priv->pipeline, GST_STATE_READY); - } -} - -static void -handle_remove_channel (PinosChannel *channel, +on_input_port_created (GObject *source_object, + GAsyncResult *res, gpointer user_data) { - PinosUploadNode *node = user_data; - PinosUploadNodePrivate *priv = node->priv; + PinosNode *node = PINOS_NODE (source_object); + PinosUploadNodePrivate *priv = PINOS_UPLOAD_NODE (source_object)->priv; - g_debug ("upload-node %p: remove channel %p", node, priv->channel); - g_clear_pointer (&priv->channel, g_object_unref); + priv->input = pinos_node_create_port_finish (node, res, NULL); } -/** - * pinos_upload_node_get_channel: - * @node: a #PinosUploadNode - * @client_path: the client path - * @format_filter: a #GBytes - * @props: extra properties - * @prefix: a path prefix - * @error: a #GError or %NULL - * - * Create a new #PinosChannel that can be used to send data to - * the pinos server. - * - * Returns: a new #PinosChannel. - */ -PinosChannel * -pinos_upload_node_get_channel (PinosUploadNode *node, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - GError **error) +static void +on_output_port_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - PinosUploadNodePrivate *priv; + PinosNode *node = PINOS_NODE (source_object); + PinosUploadNodePrivate *priv = PINOS_UPLOAD_NODE (source_object)->priv; - g_return_val_if_fail (PINOS_IS_UPLOAD_NODE (node), NULL); - priv = node->priv; - - if (priv->channel == NULL) { - GstCaps *caps = gst_caps_from_string (g_bytes_get_data (format_filter, NULL)); - - gst_caps_take (&priv->format, caps); - - priv->channel = pinos_port_create_channel (priv->input, - client_path, - format_filter, - props, - error); - if (priv->channel == NULL) - return NULL; - - g_signal_connect (priv->channel, - "remove", - (GCallback) handle_remove_channel, - node); - - g_debug ("upload-node %p: get input %p", node, priv->channel); - g_signal_connect (priv->channel, "notify::socket", (GCallback) on_input_socket_notify, node); - } - return g_object_ref (priv->channel); + priv->output = pinos_node_create_port_finish (node, res, NULL); } static void upload_node_constructed (GObject * object) { - PinosNode *node = PINOS_NODE (object); + PinosServerNode *node = PINOS_SERVER_NODE (object); PinosUploadNode *upload = PINOS_UPLOAD_NODE (object); PinosUploadNodePrivate *priv = upload->priv; G_OBJECT_CLASS (pinos_upload_node_parent_class)->constructed (object); g_debug ("upload-node %p: constructed", upload); - priv->input = pinos_port_new (pinos_node_get_daemon (node), - pinos_node_get_object_path (node), + pinos_node_create_port (PINOS_NODE (node), PINOS_DIRECTION_INPUT, "input", priv->possible_formats, - NULL); - priv->output = pinos_port_new (pinos_node_get_daemon (node), - pinos_node_get_object_path (node), + NULL, + NULL, + on_input_port_created, + node); + pinos_node_create_port (PINOS_NODE (node), PINOS_DIRECTION_OUTPUT, "output", priv->possible_formats, - NULL); - g_signal_connect (priv->output, "channel-added", (GCallback) on_channel_added, upload); - g_signal_connect (priv->output, "channel-removed", (GCallback) on_channel_removed, upload); - - pinos_node_add_port (node, priv->input); - pinos_node_add_port (node, priv->output); - + NULL, + NULL, + on_output_port_created, + node); setup_pipeline (upload); } @@ -457,11 +308,11 @@ pinos_upload_node_init (PinosUploadNode * node) * @daemon: the parent #PinosDaemon * @possible_formats: a #GBytes * - * Make a new #PinosNode that can be used to receive data from a client. + * Make a new #PinosServerNode that can be used to receive data from a client. * - * Returns: a new #PinosNode. + * Returns: a new #PinosServerNode. */ -PinosNode * +PinosServerNode * pinos_upload_node_new (PinosDaemon *daemon, GBytes *possible_formats) { diff --git a/pinos/server/upload-node.h b/pinos/server/upload-node.h index 16aefe0bf..016179f8d 100644 --- a/pinos/server/upload-node.h +++ b/pinos/server/upload-node.h @@ -28,7 +28,7 @@ typedef struct _PinosUploadNode PinosUploadNode; typedef struct _PinosUploadNodeClass PinosUploadNodeClass; typedef struct _PinosUploadNodePrivate PinosUploadNodePrivate; -#include +#include #define PINOS_TYPE_UPLOAD_NODE (pinos_upload_node_get_type ()) #define PINOS_IS_UPLOAD_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_UPLOAD_NODE)) @@ -45,7 +45,7 @@ typedef struct _PinosUploadNodePrivate PinosUploadNodePrivate; * Pinos client source object class. */ struct _PinosUploadNode { - PinosNode object; + PinosServerNode object; PinosUploadNodePrivate *priv; }; @@ -56,20 +56,15 @@ struct _PinosUploadNode { * Pinos client source object class. */ struct _PinosUploadNodeClass { - PinosNodeClass parent_class; + PinosServerNodeClass parent_class; }; /* normal GObject stuff */ GType pinos_upload_node_get_type (void); -PinosNode * pinos_upload_node_new (PinosDaemon *daemon, +PinosServerNode * pinos_upload_node_new (PinosDaemon *daemon, GBytes *possible_formats); -PinosChannel * pinos_upload_node_get_channel (PinosUploadNode *source, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - GError **error); G_END_DECLS #endif /* __PINOS_UPLOAD_NODE_H__ */ diff --git a/pinos/tools/pinos-monitor.c b/pinos/tools/pinos-monitor.c index 6d2927587..d8b25166c 100644 --- a/pinos/tools/pinos-monitor.c +++ b/pinos/tools/pinos-monitor.c @@ -166,24 +166,20 @@ dump_port_info (PinosContext *c, const PinosPortInfo *info, gpointer user_data) } } - +#if 0 static void -dump_channel_info (PinosContext *c, const PinosChannelInfo *info, gpointer user_data) +dump_connection_info (PinosContext *c, const PinosConnectionInfo *info, gpointer user_data) { DumpData *data = user_data; g_print ("\tid: %p\n", info->id); - g_print ("\tchannel-path: \"%s\"\n", info->channel_path); + g_print ("\tconnection-path: \"%s\"\n", info->connection_path); if (data->print_all) { - g_print ("\tdirection: \"%s\"\n", pinos_direction_as_string (info->direction)); - g_print ("\tclient-path: \"%s\"\n", info->client_path); - g_print ("%c\tport-path: \"%s\"\n", MARK_CHANGE (0), info->port_path); - print_properties (info->properties, MARK_CHANGE (1)); - g_print ("%c\tstate: \"%s\"\n", MARK_CHANGE (2), pinos_channel_state_as_string (info->state)); - print_formats ("possible-formats", info->possible_formats, MARK_CHANGE (3)); - print_formats ("format", info->format, MARK_CHANGE (4)); + g_print ("%c\tsource-port-path: \"%s\"\n", MARK_CHANGE (0), info->source_port_path); + g_print ("%c\tdestination-port-path: \"%s\"\n", MARK_CHANGE (1), info->destination_port_path); } } +#endif static void dump_object (PinosContext *context, gpointer id, PinosSubscriptionFlags flags, @@ -224,15 +220,6 @@ dump_object (PinosContext *context, gpointer id, PinosSubscriptionFlags flags, info_ready, data); } - else if (flags & PINOS_SUBSCRIPTION_FLAG_CHANNEL) { - pinos_context_get_channel_info_by_id (context, - id, - PINOS_CHANNEL_INFO_FLAGS_NONE, - dump_channel_info, - NULL, - info_ready, - data); - } } static void