From 91385a782e9dcde40546f03c650a9745bf9d770d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 9 May 2016 12:16:04 +0200 Subject: [PATCH] Remove vfunc from port Update docs Remove virtual functions from port, we don't want this to be changed. --- doc/design.txt | 101 +++++++++++++--------------- pinos/server/port.c | 156 ++++++++++++++++---------------------------- pinos/server/port.h | 8 --- 3 files changed, 102 insertions(+), 163 deletions(-) diff --git a/doc/design.txt b/doc/design.txt index c9af8353a..56605a4ad 100644 --- a/doc/design.txt +++ b/doc/design.txt @@ -7,7 +7,7 @@ and consume media to/from. Some of the requirements are: - must be efficient for raw video using fd passing - - must be able to provide media from any process + - must be able to provide/consume/process media from any process - streaming media only (no seeking) - policy to restrict access to devices and streams @@ -16,9 +16,7 @@ only and should be able to handle compressed video and other streamable media as well. The design is in some part inspired by pulseaudio, hence its original -name. We however are not concerned with playback of any of the media, -this should be handled by a separate consumer rendering the media to -a specific output device. +name. Increasinly we also seem to add functionality of jack. Objects @@ -46,21 +44,21 @@ DBus protocol The main daemon is registered on the session bus with name: org.pinos -Various Source1 objects are registered in the server based on the available -sources of content. Source1 has properties and has format descriptions of +Various Node1 objects are registered in the server based on the available +sources or sinks of content. Source1 has properties and has format descriptions of what it can provide. First a client needs to register with pinos by calling org.pinos.Daemon1.ConnectClient(). This creates a new Client1 object that the client must use for further communication. -A client can then do org.pinos.Client1.CreateSourceOutput() to create a -new SourceOutput1 to retrieve data from a source. It can specify a source -explicitly or let the server choose a source. The client must provide a list +A client can then do org.pinos.Client1.CreateChannel() to create a +new Channel to retrieve/send data from/to a node. It can specify a node/port +explicitly or let the server choose a port. The client must provide a list of formats it can handle along with extra properties that can help with -selecting an appropriate source. +selecting an appropriate port. -A client can then call org.pinos.SourceOutput1.Start() to negotiate the final +A client can then call org.pinos.Channel1.Start() to negotiate the final media format and start the data transfer. A new fd is returned to the client along with the negotiated format and properties. @@ -82,36 +80,30 @@ managed. * server side - v4l2src pinospay multisocketsink - | | | - | | | -make buffer |--------->| | - | | (1) | - | |------------>| (2) -----> - | | | - | |<------------| - | (4)| ............| (3) - | | | - |... | ... | - | | | - | |<------------| (5) <----- - | (6)| | - | | | + v4l2src pinossocketsink + | | + | | +make buffer |--------->| + | | (1) + | | (2) -----> + | | (3) + |... | ... + | | + | | (4) <----- + |<---------| -(1) pinospay generates the pinos message for the v4l2 input - buffer. It is assumed in the next steps that the payloader +(1) pinossocketsink generates the pinos message from the v4l2 input + buffer. It is assumed in the next steps that the sink receives fd-memory from v4l2src and that the memory is only freed again when no clients are looking at the fd. -(2) multisocketsink sends the buffer to N Pinos clients -(3) for each client that is sent a buffer, multisocketsink sends an - event with the client object and buffer in it. -(4) pinospay uses the fdmanager object to map the fd-index that was +(2) pinossocketsink sends the buffer to N Pinos clients +(3) for each client that is sent a buffer, pinossocketsink uses the + fdmanager object to map the fd-index that was sent, to the buffer and client. The buffer is reffed and kept alive for as long as the client is using the buffer. -(5) when a message is received from a client, multisocketsink sends an - event upstream. -(6) pinospay parses the message and instructs the fdmanager to release +(4) when a message is received from a client, pinossocketsink + parses the message and instructs the fdmanager to release the fd-index again. When all clients release the fd, the buffer will be unreffed and v4l2src can reuse the memory. @@ -157,34 +149,33 @@ make buffer |--------->| | * client producer, server side - socketsrc pinospay multisocketsink - | | | - ------> (1) | (2)| | - |----------->| | - | |------------>| (3) --------> - | | | .... - | (5)|<------------| (4) - | | ...... | - | | | - | (7)|<------------| (6) <-------- - <------- (8)|<-----------| | - | | | + socketsrc pinossocketsink + | | + ------> (1) | (2)| + |----------->| + | | (3) --------> + | | .... + | (4)| + | | .... + | | + | (6)| (5) <-------- + <------- (7)|<-----------| + | | (1) pinos buffer arrives from a client. socketsrc wraps the fd -(2) pinospay sets a weak-ref on the buffer to know when it is +(2) pinossocketsink sets a weak-ref on the buffer to know when it is freed. -(3) multisocketsink sends the buffer to the clients -(4) for each buffer that is sent, an event is sent to the payloader -(5) the payloader uses the fdmanager to map the fd-index to a buffer - and a client. it keeps a ref on the buffer -(6) release-fd is received from a client -(7) pinospay removes the fd-index from the fdmanager. If all +(3) pinossocketsink sends the buffer to the clients +(4) for each buffer that is sent, the sink uses the fdmanager to map the + fd-index to a buffer and a client. it keeps a ref on the buffer +(5) release-fd is received from a client +(6) pinossocketsink removes the fd-index from the fdmanager. If all clients released the fd, the buffer will be freeds, triggering the DestroyNotify. This will then trigger an event with a release-fd message to the source. -(8) the source sends the release-fd message to Pinos +(7) the source sends the release-fd message to Pinos * client remove diff --git a/pinos/server/port.c b/pinos/server/port.c index b74158e9e..0ea5b7cde 100644 --- a/pinos/server/port.c +++ b/pinos/server/port.c @@ -256,79 +256,6 @@ pinos_port_finalize (GObject * object) G_OBJECT_CLASS (pinos_port_parent_class)->finalize (object); } -static void -handle_remove_channel (PinosChannel *channel, - gpointer user_data) -{ - PinosPort *port = user_data; - - pinos_port_release_channel (port, channel); -} - -static PinosChannel * -default_create_channel (PinosPort *port, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - GError **error) -{ - PinosPortPrivate *priv = port->priv; - PinosChannel *channel; - GBytes *possible_formats; - - 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); - - 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 (PinosPort *port, - PinosChannel *channel) -{ - PinosPortPrivate *priv = port->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_port_class_init (PinosPortClass * klass) { @@ -443,9 +370,6 @@ pinos_port_class_init (PinosPortClass * klass) 1, PINOS_TYPE_CHANNEL); - - klass->create_channel = default_create_channel; - klass->release_channel = default_release_channel; } static void @@ -591,6 +515,15 @@ pinos_port_get_channels (PinosPort *port) 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 @@ -612,27 +545,49 @@ pinos_port_create_channel (PinosPort *port, PinosProperties *props, GError **error) { - PinosPortClass *klass; + PinosPortPrivate *priv; PinosChannel *channel; + GBytes *possible_formats; g_return_val_if_fail (PINOS_IS_PORT (port), NULL); + priv = port->priv; - klass = PINOS_PORT_GET_CLASS (port); + possible_formats = pinos_port_get_formats (port, format_filter, error); + if (possible_formats == NULL) + return NULL; - if (klass->create_channel) { - channel = klass->create_channel (port, client_path, format_filter, props, error); - if (channel) - g_signal_emit (port, signals[SIGNAL_CHANNEL_ADDED], 0, channel); - } else { - if (error) { + 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_NOT_SUPPORTED, - "CreateChannel not implemented"); - } - channel = NULL; + G_IO_ERROR_FAILED, + "Could not create channel"); + return NULL; } - - return channel; } /** @@ -648,20 +603,21 @@ gboolean pinos_port_release_channel (PinosPort *port, PinosChannel *channel) { - PinosPortClass *klass; - gboolean res; + 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; - klass = PINOS_PORT_GET_CLASS (port); + find = g_list_find (priv->channels, channel); + if (find == NULL) + return FALSE; - if (klass->release_channel) { - g_signal_emit (port, signals[SIGNAL_CHANNEL_REMOVED], 0, channel); - res = klass->release_channel (port, channel); - } - else - res = FALSE; + priv->channels = g_list_delete_link (priv->channels, find); - return res; + 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 index 6bf3fa834..e27fcad18 100644 --- a/pinos/server/port.h +++ b/pinos/server/port.h @@ -62,14 +62,6 @@ struct _PinosPort { */ struct _PinosPortClass { GObjectClass parent_class; - - PinosChannel * (*create_channel) (PinosPort *port, - const gchar *client_path, - GBytes *format_filter, - PinosProperties *props, - GError **error); - gboolean (*release_channel) (PinosPort *port, - PinosChannel *channel); }; /* normal GObject stuff */