| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  | /* 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 <dlfcn.h>
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <poll.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <sys/mman.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gio/gio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <spa/include/spa/node.h>
 | 
					
						
							|  |  |  | #include <spa/include/spa/monitor.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "spa-alsa-monitor.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define PINOS_SPA_ALSA_MONITOR_GET_PRIVATE(obj)  \
 | 
					
						
							|  |  |  |      (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_ALSA_MONITOR, PinosSpaALSAMonitorPrivate)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |   uint32_t node; | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   uint32_t clock; | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  | } URI; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  | struct _PinosSpaALSAMonitorPrivate | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosDaemon *daemon; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SpaHandle *handle; | 
					
						
							|  |  |  |   SpaMonitor *monitor; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |   URI uri; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   GHashTable *nodes; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PROP_0, | 
					
						
							|  |  |  |   PROP_DAEMON, | 
					
						
							|  |  |  |   PROP_MONITOR, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | G_DEFINE_TYPE (PinosSpaALSAMonitor, pinos_spa_alsa_monitor, G_TYPE_OBJECT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  | make_handle (PinosDaemon *daemon, SpaHandle **handle, const char *lib, const char *name, const SpaDict *info) | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   SpaResult res; | 
					
						
							|  |  |  |   void *hnd, *state = NULL; | 
					
						
							|  |  |  |   SpaEnumHandleFactoryFunc enum_func; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) { | 
					
						
							|  |  |  |     g_error ("can't load %s: %s", lib, dlerror()); | 
					
						
							|  |  |  |     return SPA_RESULT_ERROR; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ((enum_func = dlsym (hnd, "spa_enum_handle_factory")) == NULL) { | 
					
						
							|  |  |  |     g_error ("can't find enum function"); | 
					
						
							|  |  |  |     return SPA_RESULT_ERROR; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (true) { | 
					
						
							|  |  |  |     const SpaHandleFactory *factory; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((res = enum_func (&factory, &state)) < 0) { | 
					
						
							|  |  |  |       if (res != SPA_RESULT_ENUM_END) | 
					
						
							|  |  |  |         g_error ("can't enumerate factories: %d", res); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (strcmp (factory->name, name)) | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *handle = g_malloc0 (factory->size); | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |     if ((res = spa_handle_factory_init (factory, *handle, info, daemon->support, daemon->n_support)) < 0) { | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |       g_error ("can't make factory instance: %d", res); | 
					
						
							|  |  |  |       return res; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return SPA_RESULT_OK; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return SPA_RESULT_ERROR; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | add_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosSpaALSAMonitorPrivate *priv = this->priv; | 
					
						
							|  |  |  |   SpaResult res; | 
					
						
							|  |  |  |   SpaHandle *handle; | 
					
						
							|  |  |  |   PinosNode *node; | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   void *node_iface, *clock_iface; | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   PinosProperties *props = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_debug ("alsa-monitor %p: add: \"%s\" (%s)", this, item->name, item->id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   handle = calloc (1, item->factory->size); | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |   if ((res = spa_handle_factory_init (item->factory, | 
					
						
							|  |  |  |                                       handle, | 
					
						
							|  |  |  |                                       item->info, | 
					
						
							|  |  |  |                                       priv->daemon->support, | 
					
						
							|  |  |  |                                       priv->daemon->n_support)) < 0) { | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |     g_error ("can't make factory instance: %d", res); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if ((res = spa_handle_get_interface (handle, priv->uri.node, &node_iface)) < 0) { | 
					
						
							|  |  |  |     g_error ("can't get NODE interface: %d", res); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if ((res = spa_handle_get_interface (handle, priv->uri.clock, &clock_iface)) < 0) { | 
					
						
							|  |  |  |     g_error ("can't get CLOCK interface: %d", res); | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (item->info) { | 
					
						
							|  |  |  |     unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     props = pinos_properties_new (NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < item->info->n_items; i++) | 
					
						
							|  |  |  |       pinos_properties_set (props, | 
					
						
							|  |  |  |                             item->info->items[i].key, | 
					
						
							|  |  |  |                             item->info->items[i].value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   node = g_object_new (PINOS_TYPE_NODE, | 
					
						
							|  |  |  |                        "daemon", priv->daemon, | 
					
						
							|  |  |  |                        "name", item->factory->name, | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |                        "node", node_iface, | 
					
						
							|  |  |  |                        "clock", clock_iface, | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |                        "properties", props, | 
					
						
							|  |  |  |                        NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_hash_table_insert (priv->nodes, g_strdup (item->id), node); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | remove_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosSpaALSAMonitorPrivate *priv = this->priv; | 
					
						
							|  |  |  |   PinosNode *node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_debug ("alsa-monitor %p: remove: \"%s\" (%s)", this, item->name, item->id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   node = g_hash_table_lookup (priv->nodes, item->id); | 
					
						
							|  |  |  |   if (node) { | 
					
						
							|  |  |  |     pinos_node_remove (node); | 
					
						
							|  |  |  |     g_hash_table_remove (priv->nodes, item->id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | on_monitor_event  (SpaMonitor      *monitor, | 
					
						
							|  |  |  |                    SpaMonitorEvent *event, | 
					
						
							|  |  |  |                    void            *user_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosSpaALSAMonitor *this = user_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (event->type) { | 
					
						
							|  |  |  |     case SPA_MONITOR_EVENT_TYPE_ADDED: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       SpaMonitorItem *item = event->data; | 
					
						
							|  |  |  |       add_item (this, item); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SPA_MONITOR_EVENT_TYPE_REMOVED: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       SpaMonitorItem *item = event->data; | 
					
						
							|  |  |  |       remove_item (this, item); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SPA_MONITOR_EVENT_TYPE_CHANGED: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       SpaMonitorItem *item = event->data; | 
					
						
							|  |  |  |       g_debug ("alsa-monitor %p: changed: \"%s\"", this, item->name); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | monitor_constructed (GObject * object) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosSpaALSAMonitor *this = PINOS_SPA_ALSA_MONITOR (object); | 
					
						
							|  |  |  |   PinosSpaALSAMonitorPrivate *priv = this->priv; | 
					
						
							|  |  |  |   SpaResult res; | 
					
						
							|  |  |  |   void *state = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_debug ("spa-monitor %p: constructed", this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   G_OBJECT_CLASS (pinos_spa_alsa_monitor_parent_class)->constructed (object); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |   priv->uri.node = spa_id_map_get_id (priv->daemon->map, SPA_NODE_URI); | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   priv->uri.clock = spa_id_map_get_id (priv->daemon->map, SPA_CLOCK_URI); | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   while (TRUE) { | 
					
						
							|  |  |  |     SpaMonitorItem *item; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((res = spa_monitor_enum_items (priv->monitor, &item, &state)) < 0) { | 
					
						
							|  |  |  |       if (res != SPA_RESULT_ENUM_END) | 
					
						
							|  |  |  |         g_debug ("spa_monitor_enum_items: got error %d\n", res); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     add_item (this, item); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   spa_monitor_set_event_callback (priv->monitor, on_monitor_event, this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | monitor_get_property (GObject    *_object, | 
					
						
							|  |  |  |                       guint       prop_id, | 
					
						
							|  |  |  |                       GValue     *value, | 
					
						
							|  |  |  |                       GParamSpec *pspec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosSpaALSAMonitor *this = PINOS_SPA_ALSA_MONITOR (_object); | 
					
						
							|  |  |  |   PinosSpaALSAMonitorPrivate *priv = this->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (prop_id) { | 
					
						
							|  |  |  |     case PROP_DAEMON: | 
					
						
							|  |  |  |       g_value_set_object (value, priv->daemon); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case PROP_MONITOR: | 
					
						
							|  |  |  |       g_value_set_pointer (value, priv->monitor); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | monitor_set_property (GObject      *_object, | 
					
						
							|  |  |  |                       guint         prop_id, | 
					
						
							|  |  |  |                       const GValue *value, | 
					
						
							|  |  |  |                       GParamSpec   *pspec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosSpaALSAMonitor *this = PINOS_SPA_ALSA_MONITOR (_object); | 
					
						
							|  |  |  |   PinosSpaALSAMonitorPrivate *priv = this->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (prop_id) { | 
					
						
							|  |  |  |     case PROP_DAEMON: | 
					
						
							|  |  |  |       priv->daemon = g_value_dup_object (value); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case PROP_MONITOR: | 
					
						
							|  |  |  |       priv->monitor = g_value_get_pointer (value); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | monitor_finalize (GObject * object) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosSpaALSAMonitor *this = PINOS_SPA_ALSA_MONITOR (object); | 
					
						
							|  |  |  |   PinosSpaALSAMonitorPrivate *priv = this->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_debug ("spa-monitor %p: dispose", this); | 
					
						
							|  |  |  |   spa_handle_clear (priv->handle); | 
					
						
							|  |  |  |   g_free (priv->handle); | 
					
						
							|  |  |  |   g_hash_table_unref (priv->nodes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   G_OBJECT_CLASS (pinos_spa_alsa_monitor_parent_class)->finalize (object); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | pinos_spa_alsa_monitor_class_init (PinosSpaALSAMonitorClass * klass) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_type_class_add_private (klass, sizeof (PinosSpaALSAMonitorPrivate)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   gobject_class->constructed = monitor_constructed; | 
					
						
							|  |  |  |   gobject_class->finalize = monitor_finalize; | 
					
						
							|  |  |  |   gobject_class->set_property = monitor_set_property; | 
					
						
							|  |  |  |   gobject_class->get_property = monitor_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_MONITOR, | 
					
						
							|  |  |  |                                    g_param_spec_pointer ("monitor", | 
					
						
							|  |  |  |                                                          "Monitor", | 
					
						
							|  |  |  |                                                          "The SPA monitor", | 
					
						
							|  |  |  |                                                          G_PARAM_READWRITE | | 
					
						
							|  |  |  |                                                          G_PARAM_CONSTRUCT_ONLY | | 
					
						
							|  |  |  |                                                          G_PARAM_STATIC_STRINGS)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | pinos_spa_alsa_monitor_init (PinosSpaALSAMonitor * this) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PinosSpaALSAMonitorPrivate *priv = this->priv = PINOS_SPA_ALSA_MONITOR_GET_PRIVATE (this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   priv->nodes = g_hash_table_new_full (g_str_hash, | 
					
						
							|  |  |  |                                        g_str_equal, | 
					
						
							|  |  |  |                                        g_free, | 
					
						
							|  |  |  |                                        g_object_unref); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GObject * | 
					
						
							|  |  |  | pinos_spa_alsa_monitor_new (PinosDaemon *daemon) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GObject *monitor; | 
					
						
							|  |  |  |   SpaHandle *handle; | 
					
						
							|  |  |  |   SpaResult res; | 
					
						
							|  |  |  |   void *iface; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |   if ((res = make_handle (daemon, &handle, | 
					
						
							|  |  |  |                           "build/spa/plugins/alsa/libspa-alsa.so", | 
					
						
							|  |  |  |                           "alsa-monitor", | 
					
						
							|  |  |  |                           NULL)) < 0) { | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |     g_error ("can't create alsa-monitor: %d", res); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ((res = spa_handle_get_interface (handle, | 
					
						
							|  |  |  |                                        spa_id_map_get_id (daemon->map, SPA_MONITOR_URI), | 
					
						
							|  |  |  |                                        &iface)) < 0) { | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |     g_free (handle); | 
					
						
							|  |  |  |     g_error ("can't get MONITOR interface: %d", res); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   monitor = g_object_new (PINOS_TYPE_SPA_ALSA_MONITOR, | 
					
						
							|  |  |  |                           "daemon", daemon, | 
					
						
							|  |  |  |                           "monitor", iface, | 
					
						
							|  |  |  |                           NULL); | 
					
						
							|  |  |  |   return monitor; | 
					
						
							|  |  |  | } |