mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	channel: remove the channel
Remove the channel, the functionality is now in the client-node.
This commit is contained in:
		
							parent
							
								
									907bd7bfd7
								
							
						
					
					
						commit
						d374f50d28
					
				
					 10 changed files with 71 additions and 1060 deletions
				
			
		| 
						 | 
					@ -205,7 +205,6 @@ lib_LTLIBRARIES += libpinoscore-@PINOS_MAJORMINOR@.la
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Pure core stuff
 | 
					# Pure core stuff
 | 
				
			||||||
libpinoscore_@PINOS_MAJORMINOR@_la_SOURCES = \
 | 
					libpinoscore_@PINOS_MAJORMINOR@_la_SOURCES = \
 | 
				
			||||||
		server/channel.c server/channel.h \
 | 
					 | 
				
			||||||
		server/client.c server/client.h \
 | 
							server/client.c server/client.h \
 | 
				
			||||||
		server/client-node.c server/client-node.h \
 | 
							server/client-node.c server/client-node.h \
 | 
				
			||||||
		server/daemon.c server/daemon.h \
 | 
							server/daemon.c server/daemon.h \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -786,7 +786,7 @@ do_connect (PinosStream *stream)
 | 
				
			||||||
  g_variant_builder_add (&b, "u", 0);
 | 
					  g_variant_builder_add (&b, "u", 0);
 | 
				
			||||||
  g_variant_builder_add (&b, "s", g_bytes_get_data (priv->possible_formats, NULL));
 | 
					  g_variant_builder_add (&b, "s", g_bytes_get_data (priv->possible_formats, NULL));
 | 
				
			||||||
  g_variant_builder_add_value (&b, pinos_properties_to_variant (priv->properties));
 | 
					  g_variant_builder_add_value (&b, pinos_properties_to_variant (priv->properties));
 | 
				
			||||||
  g_variant_builder_add (&b, "s", priv->path);
 | 
					  g_variant_builder_add (&b, "s", priv->path == NULL ? "" : priv->path);
 | 
				
			||||||
  g_variant_builder_close (&b);
 | 
					  g_variant_builder_close (&b);
 | 
				
			||||||
  ports = g_variant_builder_end (&b);
 | 
					  ports = g_variant_builder_end (&b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,27 +23,6 @@
 | 
				
			||||||
    <!-- Properties: Extra properties of the daemon -->
 | 
					    <!-- Properties: Extra properties of the daemon -->
 | 
				
			||||||
    <property name='Properties' type='a{sv}' access='read' />
 | 
					    <property name='Properties' type='a{sv}' access='read' />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- CreateChannel:
 | 
					 | 
				
			||||||
         @node: the Node1 object path or / for default
 | 
					 | 
				
			||||||
         @direction: the direction of the channel
 | 
					 | 
				
			||||||
              0 = input channel
 | 
					 | 
				
			||||||
              1 = output channel
 | 
					 | 
				
			||||||
         @possible_formats: the possible formats that can be accepted
 | 
					 | 
				
			||||||
         @properties: extra properties
 | 
					 | 
				
			||||||
         @channel: the Channel object path
 | 
					 | 
				
			||||||
         @fd: a file descriptor for data transfer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
         Create a new channel to communicate with @node with given @possible_formats
 | 
					 | 
				
			||||||
    -->
 | 
					 | 
				
			||||||
    <method name='CreateChannel'>
 | 
					 | 
				
			||||||
      <arg type='s' name='node' direction='in'/>
 | 
					 | 
				
			||||||
      <arg type='u' name='direction' direction='in'/>
 | 
					 | 
				
			||||||
      <arg type='s' name='possible_formats' direction='in'/>
 | 
					 | 
				
			||||||
      <arg type='a{sv}' name='properties' direction='in'/>
 | 
					 | 
				
			||||||
      <arg type='o' name='channel' direction='out'/>
 | 
					 | 
				
			||||||
      <arg type='h' name='fd' direction='out'/>
 | 
					 | 
				
			||||||
    </method>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <!-- CreateNode:
 | 
					    <!-- CreateNode:
 | 
				
			||||||
         @factory_name: the factory name to use for the node
 | 
					         @factory_name: the factory name to use for the node
 | 
				
			||||||
         @name: the name of the node
 | 
					         @name: the name of the node
 | 
				
			||||||
| 
						 | 
					@ -59,6 +38,14 @@
 | 
				
			||||||
      <arg type='o' name='node' direction='out'/>
 | 
					      <arg type='o' name='node' direction='out'/>
 | 
				
			||||||
    </method>
 | 
					    </method>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- CreateClientNode:
 | 
				
			||||||
 | 
					         @name: the name of the node
 | 
				
			||||||
 | 
					         @Properties: extra properties
 | 
				
			||||||
 | 
					         @ports: the port descriptions
 | 
				
			||||||
 | 
					         @node: the Node1 object path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					         Create a new Node with given name and properties and ports.
 | 
				
			||||||
 | 
					    -->
 | 
				
			||||||
    <method name='CreateClientNode'>
 | 
					    <method name='CreateClientNode'>
 | 
				
			||||||
      <arg type='s' name='name' direction='in' />
 | 
					      <arg type='s' name='name' direction='in' />
 | 
				
			||||||
      <arg type='a{sv}' name='properties' direction='in'/>
 | 
					      <arg type='a{sv}' name='properties' direction='in'/>
 | 
				
			||||||
| 
						 | 
					@ -83,54 +70,12 @@
 | 
				
			||||||
    <property name='Sender' type='s' access='read' />
 | 
					    <property name='Sender' type='s' access='read' />
 | 
				
			||||||
    <!-- Name: Properties of the client -->
 | 
					    <!-- Name: Properties of the client -->
 | 
				
			||||||
    <property name='Properties' type='a{sv}' access='read' />
 | 
					    <property name='Properties' type='a{sv}' access='read' />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  </interface>
 | 
					  </interface>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <!--
 | 
					 | 
				
			||||||
      org.pinos.Channel:
 | 
					 | 
				
			||||||
      @short_description: Interface for input/output channel
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      This interface is used to control the input/output of a
 | 
					 | 
				
			||||||
      node and start/stop the media transport.
 | 
					 | 
				
			||||||
  -->
 | 
					 | 
				
			||||||
  <interface name='org.pinos.Channel1'>
 | 
					 | 
				
			||||||
    <!-- Owner: the owner node of this channel -->
 | 
					 | 
				
			||||||
    <property name='Owner' type='o' access='read' />
 | 
					 | 
				
			||||||
    <!-- type: type of the channel
 | 
					 | 
				
			||||||
          0 = input channel
 | 
					 | 
				
			||||||
          1 = output channel
 | 
					 | 
				
			||||||
    -->
 | 
					 | 
				
			||||||
    <property name='Direction' type='u' access='read' />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <property name='Node' type='o' access='read' />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <!-- Properties: extra channel properties -->
 | 
					 | 
				
			||||||
    <property name='Properties' type='a{sv}' access='read' />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <!-- state: state of the channel
 | 
					 | 
				
			||||||
          -1 = the channel is in error
 | 
					 | 
				
			||||||
          0 = the channel is idle
 | 
					 | 
				
			||||||
          1 = the channel is starting
 | 
					 | 
				
			||||||
          2 = the channel is streaming
 | 
					 | 
				
			||||||
    -->
 | 
					 | 
				
			||||||
    <property name='State' type='u' access='read' />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <!-- PossibleFormats:
 | 
					 | 
				
			||||||
         all possible formats of the channel. This is filtered
 | 
					 | 
				
			||||||
         against the accepted_formats when creating the channel.
 | 
					 | 
				
			||||||
         -->
 | 
					 | 
				
			||||||
    <property name='PossibleFormats' type='s' access='read' />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <!-- Format: the current streaming format -->
 | 
					 | 
				
			||||||
    <property name='Format' type='s' access='read' />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <!-- Remove:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
         Remove the channel
 | 
					 | 
				
			||||||
    -->
 | 
					 | 
				
			||||||
    <method name='Remove'/>
 | 
					 | 
				
			||||||
  </interface>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <!--
 | 
					  <!--
 | 
				
			||||||
      org.pinos.Node1:
 | 
					      org.pinos.Node1:
 | 
				
			||||||
      @short_description: A processing node
 | 
					      @short_description: A processing node
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,729 +0,0 @@
 | 
				
			||||||
/* Pinos
 | 
					 | 
				
			||||||
 * Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This library is free software; you can redistribute it and/or
 | 
					 | 
				
			||||||
 * modify it under the terms of the GNU Library General Public
 | 
					 | 
				
			||||||
 * License as published by the Free Software Foundation; either
 | 
					 | 
				
			||||||
 * version 2 of the License, or (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This library is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
					 | 
				
			||||||
 * Library General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Library General Public
 | 
					 | 
				
			||||||
 * License along with this library; if not, write to the
 | 
					 | 
				
			||||||
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 | 
					 | 
				
			||||||
 * Boston, MA 02110-1301, USA.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <gio/gunixfdlist.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "pinos/client/pinos.h"
 | 
					 | 
				
			||||||
#include "pinos/client/enumtypes.h"
 | 
					 | 
				
			||||||
#include "pinos/client/private.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "pinos/server/daemon.h"
 | 
					 | 
				
			||||||
#include "pinos/server/channel.h"
 | 
					 | 
				
			||||||
#include "pinos/server/utils.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "pinos/dbus/org-pinos.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MAX_BUFFER_SIZE 1024
 | 
					 | 
				
			||||||
#define MAX_FDS         16
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct _PinosChannelPrivate
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosDaemon *daemon;
 | 
					 | 
				
			||||||
  PinosChannel1 *iface;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  gchar *object_path;
 | 
					 | 
				
			||||||
  gchar *client_path;
 | 
					 | 
				
			||||||
  PinosPort *port;
 | 
					 | 
				
			||||||
  PinosDirection direction;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  GBytes *possible_formats;
 | 
					 | 
				
			||||||
  PinosProperties *properties;
 | 
					 | 
				
			||||||
  PinosChannelState state;
 | 
					 | 
				
			||||||
  GBytes *format;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  gulong send_id;
 | 
					 | 
				
			||||||
  int fd;
 | 
					 | 
				
			||||||
  GSource *socket_source;
 | 
					 | 
				
			||||||
  GSocket *sockets[2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  PinosBuffer recv_buffer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  guint8 recv_data[MAX_BUFFER_SIZE];
 | 
					 | 
				
			||||||
  int recv_fds[MAX_FDS];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  guint8 send_data[MAX_BUFFER_SIZE];
 | 
					 | 
				
			||||||
  int send_fds[MAX_FDS];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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_PORT,
 | 
					 | 
				
			||||||
  PROP_OBJECT_PATH,
 | 
					 | 
				
			||||||
  PROP_CLIENT_PATH,
 | 
					 | 
				
			||||||
  PROP_DIRECTION,
 | 
					 | 
				
			||||||
  PROP_POSSIBLE_FORMATS,
 | 
					 | 
				
			||||||
  PROP_PROPERTIES,
 | 
					 | 
				
			||||||
  PROP_FORMAT,
 | 
					 | 
				
			||||||
  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_PORT:
 | 
					 | 
				
			||||||
      g_value_set_object (value, priv->port);
 | 
					 | 
				
			||||||
      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_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_FORMAT:
 | 
					 | 
				
			||||||
      g_value_set_boxed (value, priv->format);
 | 
					 | 
				
			||||||
      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_PORT:
 | 
					 | 
				
			||||||
      priv->port = 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_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->format, g_bytes_unref);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
stop_transfer (PinosChannel *channel)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv = channel->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_debug ("channel %p: stop transfer", channel);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pinos_port_deactivate (priv->port);
 | 
					 | 
				
			||||||
  clear_formats (channel);
 | 
					 | 
				
			||||||
  priv->state = PINOS_CHANNEL_STATE_STOPPED;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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 gboolean
 | 
					 | 
				
			||||||
on_send_buffer (PinosPort    *port,
 | 
					 | 
				
			||||||
                PinosBuffer  *buffer,
 | 
					 | 
				
			||||||
                GError      **error,
 | 
					 | 
				
			||||||
                gpointer      user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosChannel *channel = user_data;
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv = channel->priv;
 | 
					 | 
				
			||||||
  gboolean res;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (priv->state == PINOS_CHANNEL_STATE_STREAMING)
 | 
					 | 
				
			||||||
    res = pinos_io_write_buffer (priv->fd, buffer, error);
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    res = TRUE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return res;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gboolean
 | 
					 | 
				
			||||||
parse_buffer (PinosChannel *channel,
 | 
					 | 
				
			||||||
              PinosBuffer *pbuf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosBufferIter it;
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv = channel->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pinos_buffer_iter_init (&it, pbuf);
 | 
					 | 
				
			||||||
  while (pinos_buffer_iter_next (&it)) {
 | 
					 | 
				
			||||||
    PinosPacketType type = pinos_buffer_iter_get_type (&it);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    switch (type) {
 | 
					 | 
				
			||||||
      case PINOS_PACKET_TYPE_FORMAT_CHANGE:
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        PinosPacketFormatChange p;
 | 
					 | 
				
			||||||
        GBytes *format, *req_format;
 | 
					 | 
				
			||||||
        GError *error = NULL;
 | 
					 | 
				
			||||||
        const gchar *format_str;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!pinos_buffer_iter_parse_format_change (&it, &p))
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        req_format = g_bytes_new_static (p.format, strlen (p.format) + 1);
 | 
					 | 
				
			||||||
        format = pinos_format_filter (priv->possible_formats, req_format, &error);
 | 
					 | 
				
			||||||
        g_bytes_unref (req_format);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (format == NULL)
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        format_str = g_bytes_get_data (format, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        g_debug ("channel %p: format change %s", channel, format_str);
 | 
					 | 
				
			||||||
        g_object_set (priv->port, "possible-formats", format, NULL);
 | 
					 | 
				
			||||||
        g_object_set (priv->iface, "format", format_str, NULL);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      case PINOS_PACKET_TYPE_START:
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        GBytes *format;
 | 
					 | 
				
			||||||
        PinosBufferBuilder builder;
 | 
					 | 
				
			||||||
        PinosPacketFormatChange fc;
 | 
					 | 
				
			||||||
        PinosBuffer obuf;
 | 
					 | 
				
			||||||
        guint8 buffer[1024];
 | 
					 | 
				
			||||||
        GError *error = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        pinos_port_activate (priv->port);
 | 
					 | 
				
			||||||
        g_object_get (priv->port, "format", &format, NULL);
 | 
					 | 
				
			||||||
        if (format == NULL)
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fc.id = 0;
 | 
					 | 
				
			||||||
        fc.format = g_bytes_get_data (format, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        g_debug ("channel %p: we are now streaming in format \"%s\"", channel, fc.format);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        priv->state = PINOS_CHANNEL_STATE_STREAMING;
 | 
					 | 
				
			||||||
        pinos_buffer_builder_init_into (&builder, buffer, 1024, NULL, 0);
 | 
					 | 
				
			||||||
        pinos_buffer_builder_add_format_change (&builder, &fc);
 | 
					 | 
				
			||||||
        pinos_buffer_builder_add_empty (&builder, PINOS_PACKET_TYPE_STREAMING);
 | 
					 | 
				
			||||||
        pinos_buffer_builder_end (&builder, &obuf);
 | 
					 | 
				
			||||||
        g_object_set (priv->iface, "state", priv->state, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!pinos_io_write_buffer (priv->fd, &obuf, &error)) {
 | 
					 | 
				
			||||||
          g_warning ("channel %p: error writing buffer: %s", channel, error->message);
 | 
					 | 
				
			||||||
          g_clear_error (&error);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      case PINOS_PACKET_TYPE_STOP:
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      case PINOS_PACKET_TYPE_REUSE_MEM:
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      default:
 | 
					 | 
				
			||||||
        g_warning ("unhandled packet %d", type);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  pinos_buffer_iter_end (&it);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gboolean
 | 
					 | 
				
			||||||
on_socket_condition (GSocket      *socket,
 | 
					 | 
				
			||||||
                     GIOCondition  condition,
 | 
					 | 
				
			||||||
                     gpointer      user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosChannel *channel = user_data;
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv = channel->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  switch (condition) {
 | 
					 | 
				
			||||||
    case G_IO_IN:
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      PinosBuffer *buffer = &priv->recv_buffer;
 | 
					 | 
				
			||||||
      GError *error = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (!pinos_io_read_buffer (priv->fd,
 | 
					 | 
				
			||||||
                                 buffer,
 | 
					 | 
				
			||||||
                                 priv->recv_data,
 | 
					 | 
				
			||||||
                                 MAX_BUFFER_SIZE,
 | 
					 | 
				
			||||||
                                 priv->recv_fds,
 | 
					 | 
				
			||||||
                                 MAX_FDS,
 | 
					 | 
				
			||||||
                                 &error)) {
 | 
					 | 
				
			||||||
        g_warning ("channel %p: failed to read buffer: %s", channel, error->message);
 | 
					 | 
				
			||||||
        g_clear_error (&error);
 | 
					 | 
				
			||||||
        return TRUE;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      parse_buffer (channel, buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (!pinos_port_receive_buffer (priv->port, buffer, &error)) {
 | 
					 | 
				
			||||||
        g_warning ("channel %p: port %p failed to receive buffer: %s", channel, priv->port, error->message);
 | 
					 | 
				
			||||||
        g_clear_error (&error);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      g_assert (pinos_buffer_unref (buffer) == FALSE);
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case G_IO_OUT:
 | 
					 | 
				
			||||||
      g_warning ("can do IO OUT\n");
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
handle_socket (PinosChannel *channel, GSocket *socket)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv = channel->priv;
 | 
					 | 
				
			||||||
  GMainContext *context = g_main_context_get_thread_default();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_debug ("channel %p: handle socket in context %p", channel, context);
 | 
					 | 
				
			||||||
  priv->fd = g_socket_get_fd (socket);
 | 
					 | 
				
			||||||
  priv->socket_source = g_socket_create_source (socket, G_IO_IN, NULL);
 | 
					 | 
				
			||||||
  g_source_set_callback (priv->socket_source, (GSourceFunc) on_socket_condition, channel, NULL);
 | 
					 | 
				
			||||||
  g_source_attach (priv->socket_source, context);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
unhandle_socket (PinosChannel *channel)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv = channel->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_debug ("channel %p: unhandle socket", channel);
 | 
					 | 
				
			||||||
  if (priv->socket_source) {
 | 
					 | 
				
			||||||
    g_source_destroy (priv->socket_source);
 | 
					 | 
				
			||||||
    g_clear_pointer (&priv->socket_source, g_source_unref);
 | 
					 | 
				
			||||||
    priv->fd = -1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * pinos_channel_get_socket_pair:
 | 
					 | 
				
			||||||
 * @channel: a #PinosChannel
 | 
					 | 
				
			||||||
 * @error: a #GError
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Create or return a previously create socket pair for @channel. The
 | 
					 | 
				
			||||||
 * Socket for the other end is returned.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns: a #GSocket that can be used to send/receive buffers to channel.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
GSocket *
 | 
					 | 
				
			||||||
pinos_channel_get_socket_pair (PinosChannel  *channel,
 | 
					 | 
				
			||||||
                               GError       **error)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_return_val_if_fail (PINOS_IS_CHANNEL (channel), FALSE);
 | 
					 | 
				
			||||||
  priv = channel->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (priv->sockets[1] == NULL) {
 | 
					 | 
				
			||||||
    int fd[2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (socketpair (AF_UNIX, SOCK_STREAM, 0, fd) != 0)
 | 
					 | 
				
			||||||
      goto no_sockets;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    priv->sockets[0] = g_socket_new_from_fd (fd[0], error);
 | 
					 | 
				
			||||||
    if (priv->sockets[0] == NULL)
 | 
					 | 
				
			||||||
      goto create_failed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    priv->sockets[1] = g_socket_new_from_fd (fd[1], error);
 | 
					 | 
				
			||||||
    if (priv->sockets[1] == NULL)
 | 
					 | 
				
			||||||
      goto create_failed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    handle_socket (channel, priv->sockets[0]);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return g_object_ref (priv->sockets[1]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* ERRORS */
 | 
					 | 
				
			||||||
no_sockets:
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    g_set_error (error,
 | 
					 | 
				
			||||||
                 G_IO_ERROR,
 | 
					 | 
				
			||||||
                 g_io_error_from_errno (errno),
 | 
					 | 
				
			||||||
                 "could not create socketpair: %s", strerror (errno));
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
create_failed:
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    g_clear_object (&priv->sockets[0]);
 | 
					 | 
				
			||||||
    g_clear_object (&priv->sockets[1]);
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
channel_register_object (PinosChannel *channel)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv = channel->priv;
 | 
					 | 
				
			||||||
  PinosObjectSkeleton *skel;
 | 
					 | 
				
			||||||
  gchar *name;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  priv->send_id = pinos_port_add_send_buffer_cb (priv->port,
 | 
					 | 
				
			||||||
                                                 on_send_buffer,
 | 
					 | 
				
			||||||
                                                 channel,
 | 
					 | 
				
			||||||
                                                 NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pinos_port_remove_send_buffer_cb (priv->port, priv->send_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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);
 | 
					 | 
				
			||||||
  pinos_port_deactivate (priv->port);
 | 
					 | 
				
			||||||
  clear_formats (channel);
 | 
					 | 
				
			||||||
  unhandle_socket (channel);
 | 
					 | 
				
			||||||
  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->port);
 | 
					 | 
				
			||||||
  g_clear_object (&priv->daemon);
 | 
					 | 
				
			||||||
  g_clear_object (&priv->iface);
 | 
					 | 
				
			||||||
  g_free (priv->client_path);
 | 
					 | 
				
			||||||
  g_free (priv->object_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_PORT,
 | 
					 | 
				
			||||||
                                   g_param_spec_object ("port",
 | 
					 | 
				
			||||||
                                                        "Port",
 | 
					 | 
				
			||||||
                                                        "The Port",
 | 
					 | 
				
			||||||
                                                        PINOS_TYPE_PORT,
 | 
					 | 
				
			||||||
                                                        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_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_FORMAT,
 | 
					 | 
				
			||||||
                                   g_param_spec_boxed ("format",
 | 
					 | 
				
			||||||
                                                       "Format",
 | 
					 | 
				
			||||||
                                                       "The format of the stream",
 | 
					 | 
				
			||||||
                                                       G_TYPE_BYTES,
 | 
					 | 
				
			||||||
                                                       G_PARAM_READWRITE |
 | 
					 | 
				
			||||||
                                                       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-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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const gchar *
 | 
					 | 
				
			||||||
pinos_channel_get_client_path (PinosChannel *channel)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosChannelPrivate *priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_return_val_if_fail (PINOS_IS_CHANNEL (channel), NULL);
 | 
					 | 
				
			||||||
  priv = channel->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return priv->client_path;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,73 +0,0 @@
 | 
				
			||||||
/* Pinos
 | 
					 | 
				
			||||||
 * Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This library is free software; you can redistribute it and/or
 | 
					 | 
				
			||||||
 * modify it under the terms of the GNU Library General Public
 | 
					 | 
				
			||||||
 * License as published by the Free Software Foundation; either
 | 
					 | 
				
			||||||
 * version 2 of the License, or (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This library is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
					 | 
				
			||||||
 * Library General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU Library General Public
 | 
					 | 
				
			||||||
 * License along with this library; if not, write to the
 | 
					 | 
				
			||||||
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 | 
					 | 
				
			||||||
 * Boston, MA 02110-1301, USA.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __PINOS_CHANNEL_H__
 | 
					 | 
				
			||||||
#define __PINOS_CHANNEL_H__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <glib-object.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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_client_path      (PinosChannel *channel);
 | 
					 | 
				
			||||||
const gchar *      pinos_channel_get_object_path      (PinosChannel *channel);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GSocket *          pinos_channel_get_socket_pair      (PinosChannel  *channel,
 | 
					 | 
				
			||||||
                                                       GError       **error);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
G_END_DECLS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* __PINOS_CHANNEL_H__ */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ enum
 | 
				
			||||||
  LAST_SIGNAL
 | 
					  LAST_SIGNAL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static guint signals[LAST_SIGNAL] = { 0 };
 | 
					//static guint signals[LAST_SIGNAL] = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
pinos_client_node_get_property (GObject    *_object,
 | 
					pinos_client_node_get_property (GObject    *_object,
 | 
				
			||||||
| 
						 | 
					@ -175,6 +175,26 @@ parse_buffer (PinosClientNode *cnode,
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      case PINOS_PACKET_TYPE_STOP:
 | 
					      case PINOS_PACKET_TYPE_STOP:
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
 | 
					        PinosBufferBuilder builder;
 | 
				
			||||||
 | 
					        PinosBuffer obuf;
 | 
				
			||||||
 | 
					        guint8 buffer[1024];
 | 
				
			||||||
 | 
					        GError *error = NULL;
 | 
				
			||||||
 | 
					        GList *ports, *walk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pinos_buffer_builder_init_into (&builder, buffer, 1024, NULL, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ports = pinos_node_get_ports (node);
 | 
				
			||||||
 | 
					        for (walk = ports; walk; walk = g_list_next (walk)) {
 | 
				
			||||||
 | 
					          port = walk->data;
 | 
				
			||||||
 | 
					          pinos_port_deactivate (port);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        pinos_buffer_builder_add_empty (&builder, PINOS_PACKET_TYPE_STOPPED);
 | 
				
			||||||
 | 
					        pinos_buffer_builder_end (&builder, &obuf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!pinos_io_write_buffer (priv->fd, &obuf, &error)) {
 | 
				
			||||||
 | 
					          g_warning ("client-node %p: error writing buffer: %s", node, error->message);
 | 
				
			||||||
 | 
					          g_clear_error (&error);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      case PINOS_PACKET_TYPE_REUSE_MEM:
 | 
					      case PINOS_PACKET_TYPE_REUSE_MEM:
 | 
				
			||||||
| 
						 | 
					@ -359,7 +379,6 @@ static void
 | 
				
			||||||
pinos_client_node_dispose (GObject * object)
 | 
					pinos_client_node_dispose (GObject * object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosClientNode *node = PINOS_CLIENT_NODE (object);
 | 
					  PinosClientNode *node = PINOS_CLIENT_NODE (object);
 | 
				
			||||||
  PinosClientNodePrivate *priv = node->priv;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_debug ("client-node %p: dispose", node);
 | 
					  g_debug ("client-node %p: dispose", node);
 | 
				
			||||||
  unhandle_socket (node);
 | 
					  unhandle_socket (node);
 | 
				
			||||||
| 
						 | 
					@ -371,7 +390,6 @@ static void
 | 
				
			||||||
pinos_client_node_finalize (GObject * object)
 | 
					pinos_client_node_finalize (GObject * object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosClientNode *node = PINOS_CLIENT_NODE (object);
 | 
					  PinosClientNode *node = PINOS_CLIENT_NODE (object);
 | 
				
			||||||
  PinosClientNodePrivate *priv = node->priv;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_debug ("client-node %p: finalize", node);
 | 
					  g_debug ("client-node %p: finalize", node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -409,7 +427,7 @@ pinos_client_node_class_init (PinosClientNodeClass * klass)
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
pinos_client_node_init (PinosClientNode * node)
 | 
					pinos_client_node_init (PinosClientNode * node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosClientNodePrivate *priv = node->priv = PINOS_CLIENT_NODE_GET_PRIVATE (node);
 | 
					  node->priv = PINOS_CLIENT_NODE_GET_PRIVATE (node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_debug ("client-node %p: new", node);
 | 
					  g_debug ("client-node %p: new", node);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,6 @@
 | 
				
			||||||
#include "pinos/server/node.h"
 | 
					#include "pinos/server/node.h"
 | 
				
			||||||
#include "pinos/server/client-node.h"
 | 
					#include "pinos/server/client-node.h"
 | 
				
			||||||
#include "pinos/server/client.h"
 | 
					#include "pinos/server/client.h"
 | 
				
			||||||
#include "pinos/server/channel.h"
 | 
					 | 
				
			||||||
#include "pinos/server/link.h"
 | 
					#include "pinos/server/link.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pinos/dbus/org-pinos.h"
 | 
					#include "pinos/dbus/org-pinos.h"
 | 
				
			||||||
| 
						 | 
					@ -106,117 +105,6 @@ sender_get_client (PinosDaemon *daemon,
 | 
				
			||||||
  return client;
 | 
					  return client;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
handle_remove_channel (PinosChannel  *channel,
 | 
					 | 
				
			||||||
                       gpointer       user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosClient *client = user_data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_debug ("client %p: remove channel %p", client, channel);
 | 
					 | 
				
			||||||
  pinos_client_remove_object (client, G_OBJECT (channel));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static gboolean
 | 
					 | 
				
			||||||
handle_create_channel (PinosDaemon1           *interface,
 | 
					 | 
				
			||||||
                       GDBusMethodInvocation  *invocation,
 | 
					 | 
				
			||||||
                       const gchar            *arg_node,
 | 
					 | 
				
			||||||
                       PinosDirection          direction,
 | 
					 | 
				
			||||||
                       const gchar            *arg_possible_formats,
 | 
					 | 
				
			||||||
                       GVariant               *arg_properties,
 | 
					 | 
				
			||||||
                       gpointer                user_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosDaemon *daemon = user_data;
 | 
					 | 
				
			||||||
  const gchar *sender, *object_path;
 | 
					 | 
				
			||||||
  PinosProperties *props;
 | 
					 | 
				
			||||||
  PinosClient *client;
 | 
					 | 
				
			||||||
  PinosPort *port;
 | 
					 | 
				
			||||||
  PinosChannel *channel;
 | 
					 | 
				
			||||||
  GBytes *formats;
 | 
					 | 
				
			||||||
  GError *error = NULL;
 | 
					 | 
				
			||||||
  GUnixFDList *fdlist;
 | 
					 | 
				
			||||||
  GSocket *socket;
 | 
					 | 
				
			||||||
  gint fdidx;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  sender = g_dbus_method_invocation_get_sender (invocation);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_debug ("daemon %p: %s create channel", daemon, sender);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  formats = g_bytes_new (arg_possible_formats, strlen (arg_possible_formats) + 1);
 | 
					 | 
				
			||||||
  props = pinos_properties_from_variant (arg_properties);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  port = pinos_daemon_find_port (daemon,
 | 
					 | 
				
			||||||
                                 direction,
 | 
					 | 
				
			||||||
                                 arg_node,
 | 
					 | 
				
			||||||
                                 props,
 | 
					 | 
				
			||||||
                                 formats,
 | 
					 | 
				
			||||||
                                 &error);
 | 
					 | 
				
			||||||
  if (port == NULL)
 | 
					 | 
				
			||||||
    goto no_port;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_debug ("daemon %p: matched port %p", daemon, port);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  client = sender_get_client (daemon, sender);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  channel = pinos_port_create_channel (port,
 | 
					 | 
				
			||||||
                                       pinos_client_get_object_path (client),
 | 
					 | 
				
			||||||
                                       formats,
 | 
					 | 
				
			||||||
                                       props,
 | 
					 | 
				
			||||||
                                       &error);
 | 
					 | 
				
			||||||
  pinos_properties_free (props);
 | 
					 | 
				
			||||||
  g_bytes_unref (formats);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (channel == NULL)
 | 
					 | 
				
			||||||
    goto no_channel;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pinos_client_add_object (client, G_OBJECT (channel));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_signal_connect (channel,
 | 
					 | 
				
			||||||
                    "remove",
 | 
					 | 
				
			||||||
                    (GCallback) handle_remove_channel,
 | 
					 | 
				
			||||||
                    client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  socket = pinos_channel_get_socket_pair (channel, &error);
 | 
					 | 
				
			||||||
  if (socket == NULL)
 | 
					 | 
				
			||||||
    goto no_socket;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  object_path = pinos_channel_get_object_path (channel);
 | 
					 | 
				
			||||||
  g_debug ("daemon %p: add channel %p, %s", daemon, channel, object_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  fdlist = g_unix_fd_list_new ();
 | 
					 | 
				
			||||||
  fdidx = g_unix_fd_list_append (fdlist, g_socket_get_fd (socket), NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,
 | 
					 | 
				
			||||||
           g_variant_new ("(oh)", object_path, fdidx), fdlist);
 | 
					 | 
				
			||||||
  g_object_unref (fdlist);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return TRUE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* ERRORS */
 | 
					 | 
				
			||||||
no_port:
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    g_debug ("daemon %p: could not find port %s, %s", daemon, arg_node, error->message);
 | 
					 | 
				
			||||||
    pinos_properties_free (props);
 | 
					 | 
				
			||||||
    g_bytes_unref (formats);
 | 
					 | 
				
			||||||
    goto exit_error;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
no_channel:
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    g_debug ("daemon %p: could not create channel %s", daemon, error->message);
 | 
					 | 
				
			||||||
    goto exit_error;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
no_socket:
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    g_debug ("daemon %p: could not create channel %s", daemon, error->message);
 | 
					 | 
				
			||||||
    goto exit_error;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
exit_error:
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    g_dbus_method_invocation_return_gerror (invocation, error);
 | 
					 | 
				
			||||||
    g_clear_error (&error);
 | 
					 | 
				
			||||||
    return TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
handle_remove_node (PinosNode *node,
 | 
					handle_remove_node (PinosNode *node,
 | 
				
			||||||
                    gpointer   user_data)
 | 
					                    gpointer   user_data)
 | 
				
			||||||
| 
						 | 
					@ -356,8 +244,13 @@ handle_create_client_node (PinosDaemon1           *interface,
 | 
				
			||||||
                                       pprops,
 | 
					                                       pprops,
 | 
				
			||||||
                                       formats,
 | 
					                                       formats,
 | 
				
			||||||
                                       &error);
 | 
					                                       &error);
 | 
				
			||||||
      if (target == NULL)
 | 
					      if (target == NULL) {
 | 
				
			||||||
 | 
					        g_warning ("daemon %p: can't find port target: %s", daemon, error->message);
 | 
				
			||||||
 | 
					        g_clear_error (&error);
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      pinos_client_add_object (client, G_OBJECT (target));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      link = pinos_link_new (daemon, port, target, NULL);
 | 
					      link = pinos_link_new (daemon, port, target, NULL);
 | 
				
			||||||
      pinos_client_add_object (client, G_OBJECT (link));
 | 
					      pinos_client_add_object (client, G_OBJECT (link));
 | 
				
			||||||
| 
						 | 
					@ -653,7 +546,7 @@ pinos_daemon_find_port (PinosDaemon     *daemon,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  have_name = name ? strlen (name) > 0 : FALSE;
 | 
					  have_name = name ? strlen (name) > 0 : FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_debug ("name %s, format %s", name, (gchar*)g_bytes_get_data (format_filter, NULL));
 | 
					  g_debug ("name %s, format %s, %d", name, (gchar*)g_bytes_get_data (format_filter, NULL), have_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (nodes = priv->nodes; nodes; nodes = g_list_next (nodes)) {
 | 
					  for (nodes = priv->nodes; nodes; nodes = g_list_next (nodes)) {
 | 
				
			||||||
    PinosNode *n = nodes->data;
 | 
					    PinosNode *n = nodes->data;
 | 
				
			||||||
| 
						 | 
					@ -662,7 +555,10 @@ pinos_daemon_find_port (PinosDaemon     *daemon,
 | 
				
			||||||
    g_debug ("node path %s", pinos_node_get_object_path (n));
 | 
					    g_debug ("node path %s", pinos_node_get_object_path (n));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* we found the node */
 | 
					    /* we found the node */
 | 
				
			||||||
    if (have_name && g_str_has_suffix (pinos_node_get_object_path (n), name)) {
 | 
					    if (have_name) {
 | 
				
			||||||
 | 
					      if (!g_str_has_suffix (pinos_node_get_object_path (n), name))
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      g_debug ("name \"%s\" matches node %p", name, n);
 | 
					      g_debug ("name \"%s\" matches node %p", name, n);
 | 
				
			||||||
      node_found = TRUE;
 | 
					      node_found = TRUE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -842,7 +738,6 @@ pinos_daemon_init (PinosDaemon * daemon)
 | 
				
			||||||
  priv->iface = pinos_daemon1_skeleton_new ();
 | 
					  priv->iface = pinos_daemon1_skeleton_new ();
 | 
				
			||||||
  g_signal_connect (priv->iface, "handle-create-node", (GCallback) handle_create_node, daemon);
 | 
					  g_signal_connect (priv->iface, "handle-create-node", (GCallback) handle_create_node, daemon);
 | 
				
			||||||
  g_signal_connect (priv->iface, "handle-create-client-node", (GCallback) handle_create_client_node, daemon);
 | 
					  g_signal_connect (priv->iface, "handle-create-client-node", (GCallback) handle_create_client_node, daemon);
 | 
				
			||||||
  g_signal_connect (priv->iface, "handle-create-channel", (GCallback) handle_create_channel, daemon);
 | 
					 | 
				
			||||||
  g_signal_connect (priv->iface, "handle-link-nodes", (GCallback) handle_link_nodes, daemon);
 | 
					  g_signal_connect (priv->iface, "handle-link-nodes", (GCallback) handle_link_nodes, daemon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  priv->server_manager = g_dbus_object_manager_server_new (PINOS_DBUS_OBJECT_PREFIX);
 | 
					  priv->server_manager = g_dbus_object_manager_server_new (PINOS_DBUS_OBJECT_PREFIX);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,8 @@ struct _PinosLinkPrivate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  gchar *object_path;
 | 
					  gchar *object_path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  gulong input_id, output_id;
 | 
				
			||||||
 | 
					  gboolean active;
 | 
				
			||||||
  PinosPort *output;
 | 
					  PinosPort *output;
 | 
				
			||||||
  PinosPort *input;
 | 
					  PinosPort *input;
 | 
				
			||||||
  GBytes *possible_formats;
 | 
					  GBytes *possible_formats;
 | 
				
			||||||
| 
						 | 
					@ -203,10 +205,14 @@ on_activate (PinosPort *port, gpointer user_data)
 | 
				
			||||||
  PinosLink *link = user_data;
 | 
					  PinosLink *link = user_data;
 | 
				
			||||||
  PinosLinkPrivate *priv = link->priv;
 | 
					  PinosLinkPrivate *priv = link->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (priv->active)
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (priv->input == port)
 | 
					  if (priv->input == port)
 | 
				
			||||||
    pinos_port_activate (priv->output);
 | 
					    pinos_port_activate (priv->output);
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    pinos_port_activate (priv->input);
 | 
					    pinos_port_activate (priv->input);
 | 
				
			||||||
 | 
					  priv->active = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return TRUE;
 | 
					  return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -217,10 +223,14 @@ on_deactivate (PinosPort *port, gpointer user_data)
 | 
				
			||||||
  PinosLink *link = user_data;
 | 
					  PinosLink *link = user_data;
 | 
				
			||||||
  PinosLinkPrivate *priv = link->priv;
 | 
					  PinosLinkPrivate *priv = link->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!priv->active)
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (priv->input == port)
 | 
					  if (priv->input == port)
 | 
				
			||||||
    pinos_port_deactivate (priv->output);
 | 
					    pinos_port_deactivate (priv->output);
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    pinos_port_deactivate (priv->input);
 | 
					    pinos_port_deactivate (priv->input);
 | 
				
			||||||
 | 
					  priv->active = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return TRUE;
 | 
					  return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -232,18 +242,20 @@ pinos_link_constructed (GObject * object)
 | 
				
			||||||
  PinosLinkPrivate *priv = link->priv;
 | 
					  PinosLinkPrivate *priv = link->priv;
 | 
				
			||||||
  GBytes *formats;
 | 
					  GBytes *formats;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_port_add_send_buffer_cb (priv->output,
 | 
					  priv->output_id = pinos_port_add_send_buffer_cb (priv->output,
 | 
				
			||||||
                                 on_output_send,
 | 
					                                 on_output_send,
 | 
				
			||||||
                                 link,
 | 
					                                 link,
 | 
				
			||||||
                                 NULL);
 | 
					                                 NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_port_add_send_buffer_cb (priv->input,
 | 
					  priv->input_id = pinos_port_add_send_buffer_cb (priv->input,
 | 
				
			||||||
                                 on_input_send,
 | 
					                                 on_input_send,
 | 
				
			||||||
                                 link,
 | 
					                                 link,
 | 
				
			||||||
                                 NULL);
 | 
					                                 NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_object_get (priv->input, "possible-formats", &formats, NULL);
 | 
					  g_object_get (priv->input, "possible-formats", &formats, NULL);
 | 
				
			||||||
  g_object_set (priv->output, "possible-formats", formats, NULL);
 | 
					  g_object_set (priv->output, "possible-formats", formats, NULL);
 | 
				
			||||||
 | 
					  g_object_get (priv->output, "format", &formats, NULL);
 | 
				
			||||||
 | 
					  g_object_set (priv->input, "format", formats, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_signal_connect (priv->input, "activate", (GCallback) on_activate, link);
 | 
					  g_signal_connect (priv->input, "activate", (GCallback) on_activate, link);
 | 
				
			||||||
  g_signal_connect (priv->input, "deactivate", (GCallback) on_deactivate, link);
 | 
					  g_signal_connect (priv->input, "deactivate", (GCallback) on_deactivate, link);
 | 
				
			||||||
| 
						 | 
					@ -260,8 +272,19 @@ static void
 | 
				
			||||||
pinos_link_dispose (GObject * object)
 | 
					pinos_link_dispose (GObject * object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosLink *link = PINOS_LINK (object);
 | 
					  PinosLink *link = PINOS_LINK (object);
 | 
				
			||||||
 | 
					  PinosLinkPrivate *priv = link->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_debug ("link %p: dispose", link);
 | 
					  g_debug ("link %p: dispose", link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pinos_port_remove_send_buffer_cb (priv->input, priv->input_id);
 | 
				
			||||||
 | 
					  pinos_port_remove_send_buffer_cb (priv->output, priv->output_id);
 | 
				
			||||||
 | 
					  if (priv->active) {
 | 
				
			||||||
 | 
					    priv->active = FALSE;
 | 
				
			||||||
 | 
					    pinos_port_deactivate (priv->input);
 | 
				
			||||||
 | 
					    pinos_port_deactivate (priv->output);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  g_clear_object (&priv->input);
 | 
				
			||||||
 | 
					  g_clear_object (&priv->output);
 | 
				
			||||||
  link_unregister_object (link);
 | 
					  link_unregister_object (link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object);
 | 
					  G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -625,66 +625,6 @@ parse_control_buffer (PinosPort *port, PinosBuffer *buffer)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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_filter_formats (port, format_filter, error);
 | 
					 | 
				
			||||||
  if (possible_formats == NULL)
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  g_debug ("port %p: make channel with formats %s", port,
 | 
					 | 
				
			||||||
      (gchar *) g_bytes_get_data (possible_formats, NULL));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  channel = g_object_new (PINOS_TYPE_CHANNEL, "daemon", priv->daemon,
 | 
					 | 
				
			||||||
                                              "port", port,
 | 
					 | 
				
			||||||
                                              "client-path", client_path,
 | 
					 | 
				
			||||||
                                              "direction", priv->direction,
 | 
					 | 
				
			||||||
                                              "possible-formats", possible_formats,
 | 
					 | 
				
			||||||
                                              "properties", props,
 | 
					 | 
				
			||||||
                                              NULL);
 | 
					 | 
				
			||||||
  g_bytes_unref (possible_formats);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (channel == NULL)
 | 
					 | 
				
			||||||
    goto no_channel;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return channel;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* ERRORS */
 | 
					 | 
				
			||||||
no_channel:
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    if (error)
 | 
					 | 
				
			||||||
      *error = g_error_new (G_IO_ERROR,
 | 
					 | 
				
			||||||
                            G_IO_ERROR_FAILED,
 | 
					 | 
				
			||||||
                            "Could not create channel");
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
pinos_port_activate (PinosPort *port)
 | 
					pinos_port_activate (PinosPort *port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,6 @@ typedef struct _PinosPortPrivate PinosPortPrivate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pinos/client/introspect.h>
 | 
					#include <pinos/client/introspect.h>
 | 
				
			||||||
#include <pinos/client/buffer.h>
 | 
					#include <pinos/client/buffer.h>
 | 
				
			||||||
#include <pinos/server/channel.h>
 | 
					 | 
				
			||||||
#include <pinos/server/daemon.h>
 | 
					#include <pinos/server/daemon.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PINOS_TYPE_PORT             (pinos_port_get_type ())
 | 
					#define PINOS_TYPE_PORT             (pinos_port_get_type ())
 | 
				
			||||||
| 
						 | 
					@ -95,12 +94,6 @@ GBytes *            pinos_port_get_format           (PinosPort *port);
 | 
				
			||||||
void                pinos_port_activate             (PinosPort *port);
 | 
					void                pinos_port_activate             (PinosPort *port);
 | 
				
			||||||
void                pinos_port_deactivate           (PinosPort *port);
 | 
					void                pinos_port_deactivate           (PinosPort *port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PinosChannel *      pinos_port_create_channel	    (PinosPort       *port,
 | 
					 | 
				
			||||||
                                                     const gchar     *client_path,
 | 
					 | 
				
			||||||
                                                     GBytes          *format_filter,
 | 
					 | 
				
			||||||
                                                     PinosProperties *props,
 | 
					 | 
				
			||||||
                                                     GError         **error);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
gboolean            pinos_port_send_buffer          (PinosPort   *port,
 | 
					gboolean            pinos_port_send_buffer          (PinosPort   *port,
 | 
				
			||||||
                                                     PinosBuffer *buffer,
 | 
					                                                     PinosBuffer *buffer,
 | 
				
			||||||
                                                     GError     **error);
 | 
					                                                     GError     **error);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue