| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | /* Spa ALSA Sink
 | 
					
						
							|  |  |  |  * Copyright (C) 2016 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 <stddef.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asoundlib.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <spa/node.h>
 | 
					
						
							| 
									
										
										
										
											2016-07-05 17:58:34 +02:00
										 |  |  | #include <spa/audio/format.h>
 | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  | #include <lib/props.h>
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  | #include "alsa-utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  | #define CHECK_PORT(this,d,p)    ((d) == SPA_DIRECTION_INPUT && (p) == 0)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  | typedef struct _SpaALSAState SpaALSASink; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static const char default_device[] = "default"; | 
					
						
							|  |  |  | static const uint32_t default_buffer_time = 10000; | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  | static const uint32_t default_period_time = 1000; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | static const bool default_period_event = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  | reset_alsa_sink_props (SpaALSAProps *props) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   strncpy (props->device, default_device, 64); | 
					
						
							|  |  |  |   props->buffer_time = default_buffer_time; | 
					
						
							|  |  |  |   props->period_time = default_period_time; | 
					
						
							|  |  |  |   props->period_event = default_period_event; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 15:25:53 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | update_state (SpaALSASink *this, SpaNodeState state) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |   spa_log_info (this->log, "update state %d", state); | 
					
						
							| 
									
										
										
										
											2016-09-12 15:25:53 +02:00
										 |  |  |   this->node.state = state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | static const uint32_t min_uint32 = 1; | 
					
						
							|  |  |  | static const uint32_t max_uint32 = UINT32_MAX; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SpaPropRangeInfo uint32_range[] = { | 
					
						
							| 
									
										
										
										
											2016-10-13 19:25:49 +02:00
										 |  |  |   { "min", { 4, &min_uint32 } }, | 
					
						
							|  |  |  |   { "max", { 4, &max_uint32 } }, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |   PROP_ID_DEVICE, | 
					
						
							|  |  |  |   PROP_ID_DEVICE_NAME, | 
					
						
							|  |  |  |   PROP_ID_CARD_NAME, | 
					
						
							|  |  |  |   PROP_ID_BUFFER_TIME, | 
					
						
							|  |  |  |   PROP_ID_PERIOD_TIME, | 
					
						
							|  |  |  |   PROP_ID_PERIOD_EVENT, | 
					
						
							|  |  |  |   PROP_ID_LAST, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const SpaPropInfo prop_info[] = | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   { PROP_ID_DEVICE,             offsetof (SpaALSAProps, device), | 
					
						
							| 
									
										
										
										
											2016-10-13 19:25:49 +02:00
										 |  |  |                                 "device", | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                 SPA_PROP_FLAG_READWRITE, | 
					
						
							|  |  |  |                                 SPA_PROP_TYPE_STRING, 63, | 
					
						
							|  |  |  |                                 SPA_PROP_RANGE_TYPE_NONE, 0, NULL, | 
					
						
							| 
									
										
										
										
											2016-08-26 17:43:48 +02:00
										 |  |  |                                 NULL }, | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   { PROP_ID_DEVICE_NAME,        offsetof (SpaALSAProps, device_name), | 
					
						
							| 
									
										
										
										
											2016-10-13 19:25:49 +02:00
										 |  |  |                                 "device-name", | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                 SPA_PROP_FLAG_READABLE, | 
					
						
							|  |  |  |                                 SPA_PROP_TYPE_STRING, 127, | 
					
						
							|  |  |  |                                 SPA_PROP_RANGE_TYPE_NONE, 0, NULL, | 
					
						
							| 
									
										
										
										
											2016-08-26 17:43:48 +02:00
										 |  |  |                                 NULL }, | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   { PROP_ID_CARD_NAME,          offsetof (SpaALSAProps, card_name), | 
					
						
							| 
									
										
										
										
											2016-10-13 19:25:49 +02:00
										 |  |  |                                 "card-name", | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                 SPA_PROP_FLAG_READABLE, | 
					
						
							|  |  |  |                                 SPA_PROP_TYPE_STRING, 127, | 
					
						
							|  |  |  |                                 SPA_PROP_RANGE_TYPE_NONE, 0, NULL, | 
					
						
							| 
									
										
										
										
											2016-08-26 17:43:48 +02:00
										 |  |  |                                 NULL }, | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   { PROP_ID_BUFFER_TIME,        offsetof (SpaALSAProps, buffer_time), | 
					
						
							| 
									
										
										
										
											2016-10-13 19:25:49 +02:00
										 |  |  |                                 "buffer-time", | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                 SPA_PROP_FLAG_READWRITE, | 
					
						
							|  |  |  |                                 SPA_PROP_TYPE_UINT32, sizeof (uint32_t), | 
					
						
							|  |  |  |                                 SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, | 
					
						
							| 
									
										
										
										
											2016-08-26 17:43:48 +02:00
										 |  |  |                                 NULL }, | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   { PROP_ID_PERIOD_TIME,        offsetof (SpaALSAProps, period_time), | 
					
						
							| 
									
										
										
										
											2016-10-13 19:25:49 +02:00
										 |  |  |                                 "period-time", | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                 SPA_PROP_FLAG_READWRITE, | 
					
						
							|  |  |  |                                 SPA_PROP_TYPE_UINT32, sizeof (uint32_t), | 
					
						
							|  |  |  |                                 SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, | 
					
						
							| 
									
										
										
										
											2016-08-26 17:43:48 +02:00
										 |  |  |                                 NULL }, | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   { PROP_ID_PERIOD_EVENT,       offsetof (SpaALSAProps, period_event), | 
					
						
							| 
									
										
										
										
											2016-10-13 19:25:49 +02:00
										 |  |  |                                 "period-event", | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                 SPA_PROP_FLAG_READWRITE, | 
					
						
							|  |  |  |                                 SPA_PROP_TYPE_BOOL, sizeof (bool), | 
					
						
							|  |  |  |                                 SPA_PROP_RANGE_TYPE_NONE, 0, NULL, | 
					
						
							| 
									
										
										
										
											2016-08-26 17:43:48 +02:00
										 |  |  |                                 NULL }, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_get_props (SpaNode       *node, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                               SpaProps     **props) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL || props == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 09:30:18 +02:00
										 |  |  |   memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); | 
					
						
							|  |  |  |   *props = &this->props[0].props; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_set_props (SpaNode         *node, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                               const SpaProps  *props) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   SpaALSAProps *p; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   SpaResult res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   p = &this->props[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   if (props == NULL) { | 
					
						
							|  |  |  |     reset_alsa_sink_props (p); | 
					
						
							|  |  |  |     return SPA_RESULT_OK; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 18:18:59 +02:00
										 |  |  |   res = spa_props_copy_values (props, &p->props); | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  | static SpaResult | 
					
						
							|  |  |  | do_send_event (SpaPoll        *poll, | 
					
						
							|  |  |  |                bool            async, | 
					
						
							|  |  |  |                uint32_t        seq, | 
					
						
							|  |  |  |                size_t          size, | 
					
						
							|  |  |  |                void           *data, | 
					
						
							|  |  |  |                void           *user_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SpaALSASink *this = user_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   this->event_cb (&this->node, data, this->user_data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							|  |  |  | do_command (SpaPoll        *poll, | 
					
						
							|  |  |  |             bool            async, | 
					
						
							|  |  |  |             uint32_t        seq, | 
					
						
							|  |  |  |             size_t          size, | 
					
						
							|  |  |  |             void           *data, | 
					
						
							|  |  |  |             void           *user_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SpaALSASink *this = user_data; | 
					
						
							|  |  |  |   SpaResult res; | 
					
						
							|  |  |  |   SpaNodeCommand *cmd = data; | 
					
						
							|  |  |  |   SpaNodeEventAsyncComplete ac; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (cmd->type) { | 
					
						
							|  |  |  |     case SPA_NODE_COMMAND_START: | 
					
						
							|  |  |  |     case SPA_NODE_COMMAND_PAUSE: | 
					
						
							|  |  |  |       res = spa_node_port_send_command (&this->node, | 
					
						
							|  |  |  |                                         SPA_DIRECTION_INPUT, | 
					
						
							|  |  |  |                                         0, | 
					
						
							|  |  |  |                                         cmd); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       res = SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (async) { | 
					
						
							|  |  |  |     ac.event.type = SPA_NODE_EVENT_TYPE_ASYNC_COMPLETE; | 
					
						
							|  |  |  |     ac.event.size = sizeof (SpaNodeEventAsyncComplete); | 
					
						
							|  |  |  |     ac.seq = seq; | 
					
						
							|  |  |  |     ac.res = res; | 
					
						
							|  |  |  |     spa_poll_invoke (this->main_loop, | 
					
						
							|  |  |  |                      do_send_event, | 
					
						
							|  |  |  |                      SPA_ID_INVALID, | 
					
						
							|  |  |  |                      sizeof (ac), | 
					
						
							|  |  |  |                      &ac, | 
					
						
							|  |  |  |                      this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-09-06 16:43:37 +02:00
										 |  |  | spa_alsa_sink_node_send_command (SpaNode        *node, | 
					
						
							|  |  |  |                                  SpaNodeCommand *command) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL || command == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   switch (command->type) { | 
					
						
							| 
									
										
										
										
											2016-09-06 16:43:37 +02:00
										 |  |  |     case SPA_NODE_COMMAND_INVALID: | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |       return SPA_RESULT_INVALID_COMMAND; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-06 16:43:37 +02:00
										 |  |  |     case SPA_NODE_COMMAND_START: | 
					
						
							|  |  |  |     case SPA_NODE_COMMAND_PAUSE: | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (!this->have_format) | 
					
						
							|  |  |  |         return SPA_RESULT_NO_FORMAT; | 
					
						
							| 
									
										
										
										
											2016-07-06 19:43:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |       if (this->n_buffers == 0) | 
					
						
							|  |  |  |         return SPA_RESULT_NO_BUFFERS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return spa_poll_invoke (this->data_loop, | 
					
						
							|  |  |  |                               do_command, | 
					
						
							|  |  |  |                               ++this->seq, | 
					
						
							|  |  |  |                               command->size, | 
					
						
							|  |  |  |                               command, | 
					
						
							|  |  |  |                               this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-06 16:43:37 +02:00
										 |  |  |     case SPA_NODE_COMMAND_FLUSH: | 
					
						
							|  |  |  |     case SPA_NODE_COMMAND_DRAIN: | 
					
						
							|  |  |  |     case SPA_NODE_COMMAND_MARKER: | 
					
						
							| 
									
										
										
										
											2016-09-09 16:05:58 +02:00
										 |  |  |     case SPA_NODE_COMMAND_CLOCK_UPDATE: | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |       return SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-09-06 16:43:37 +02:00
										 |  |  | spa_alsa_sink_node_set_event_callback (SpaNode              *node, | 
					
						
							|  |  |  |                                        SpaNodeEventCallback  event, | 
					
						
							|  |  |  |                                        void                 *user_data) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   this->event_cb = event; | 
					
						
							|  |  |  |   this->user_data = user_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_get_n_ports (SpaNode       *node, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                 unsigned int  *n_input_ports, | 
					
						
							|  |  |  |                                 unsigned int  *max_input_ports, | 
					
						
							|  |  |  |                                 unsigned int  *n_output_ports, | 
					
						
							|  |  |  |                                 unsigned int  *max_output_ports) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (n_input_ports) | 
					
						
							|  |  |  |     *n_input_ports = 1; | 
					
						
							|  |  |  |   if (max_input_ports) | 
					
						
							|  |  |  |     *max_input_ports = 1; | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |   if (n_output_ports) | 
					
						
							|  |  |  |     *n_output_ports = 0; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   if (max_output_ports) | 
					
						
							|  |  |  |     *max_output_ports = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_get_port_ids (SpaNode       *node, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                  unsigned int   n_input_ports, | 
					
						
							|  |  |  |                                  uint32_t      *input_ids, | 
					
						
							|  |  |  |                                  unsigned int   n_output_ports, | 
					
						
							|  |  |  |                                  uint32_t      *output_ids) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-05 16:23:40 +02:00
										 |  |  |   if (n_input_ports > 0 && input_ids != NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     input_ids[0] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_add_port (SpaNode        *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                              SpaDirection    direction, | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |                              uint32_t        port_id) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   return SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_remove_port (SpaNode        *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                 SpaDirection    direction, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                 uint32_t        port_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_port_enum_formats (SpaNode         *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                       SpaDirection     direction, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                       uint32_t         port_id, | 
					
						
							| 
									
										
										
										
											2016-07-15 18:22:29 +02:00
										 |  |  |                                       SpaFormat      **format, | 
					
						
							|  |  |  |                                       const SpaFormat *filter, | 
					
						
							|  |  |  |                                       void           **state) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-07-15 18:22:29 +02:00
										 |  |  |   int index; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL || format == NULL || state == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |   if (!CHECK_PORT (this, direction, port_id)) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-15 18:22:29 +02:00
										 |  |  |   index = (*state == NULL ? 0 : *(int*)state); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   switch (index) { | 
					
						
							|  |  |  |     case 0: | 
					
						
							| 
									
										
										
										
											2016-08-26 19:22:50 +02:00
										 |  |  |       spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, | 
					
						
							|  |  |  |                              SPA_MEDIA_SUBTYPE_RAW, | 
					
						
							|  |  |  |                              &this->query_format); | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case 1: | 
					
						
							| 
									
										
										
										
											2016-08-26 19:22:50 +02:00
										 |  |  |       spa_format_audio_init (SPA_MEDIA_TYPE_AUDIO, | 
					
						
							|  |  |  |                              SPA_MEDIA_SUBTYPE_AAC, | 
					
						
							|  |  |  |                              &this->query_format); | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return SPA_RESULT_ENUM_END; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   *format = &this->query_format.format; | 
					
						
							| 
									
										
										
										
											2016-07-15 18:22:29 +02:00
										 |  |  |   *(int*)state = ++index; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  | static SpaResult | 
					
						
							|  |  |  | spa_alsa_clear_buffers (SpaALSASink *this) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (this->n_buffers > 0) { | 
					
						
							|  |  |  |     SPA_QUEUE_INIT (&this->ready); | 
					
						
							|  |  |  |     this->n_buffers = 0; | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |     this->ringbuffer = NULL; | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_port_set_format (SpaNode            *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                     SpaDirection        direction, | 
					
						
							| 
									
										
										
										
											2016-07-18 10:35:02 +02:00
										 |  |  |                                     uint32_t            port_id, | 
					
						
							|  |  |  |                                     SpaPortFormatFlags  flags, | 
					
						
							|  |  |  |                                     const SpaFormat    *format) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   SpaResult res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |   if (!CHECK_PORT (this, direction, port_id)) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (format == NULL) { | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |     spa_log_info (this->log, "clear format"); | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |     spa_alsa_pause (this, false); | 
					
						
							|  |  |  |     spa_alsa_clear_buffers (this); | 
					
						
							|  |  |  |     spa_alsa_close (this); | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     this->have_format = false; | 
					
						
							| 
									
										
										
										
											2016-09-12 15:25:53 +02:00
										 |  |  |     update_state (this, SPA_NODE_STATE_CONFIGURE); | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_OK; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-26 19:22:50 +02:00
										 |  |  |   if ((res = spa_format_audio_parse (format, &this->current_format)) < 0) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   if (spa_alsa_set_format (this, &this->current_format, flags) < 0) | 
					
						
							| 
									
										
										
										
											2016-08-18 12:43:25 +02:00
										 |  |  |     return SPA_RESULT_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | | 
					
						
							|  |  |  |                      SPA_PORT_INFO_FLAG_LIVE; | 
					
						
							|  |  |  |   this->info.maxbuffering = this->buffer_frames * this->frame_size; | 
					
						
							|  |  |  |   this->info.latency = (this->period_frames * SPA_NSEC_PER_SEC) / this->rate; | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |   this->info.n_params = 3; | 
					
						
							| 
									
										
										
										
											2016-09-12 15:25:53 +02:00
										 |  |  |   this->info.params = this->params; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:26:58 +02:00
										 |  |  |   this->params[0] = &this->param_buffers.param; | 
					
						
							|  |  |  |   this->param_buffers.param.type = SPA_ALLOC_PARAM_TYPE_BUFFERS; | 
					
						
							|  |  |  |   this->param_buffers.param.size = sizeof (this->param_buffers); | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   this->param_buffers.minsize = this->period_frames * this->frame_size; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:26:58 +02:00
										 |  |  |   this->param_buffers.stride = 0; | 
					
						
							|  |  |  |   this->param_buffers.min_buffers = 1; | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   this->param_buffers.max_buffers = 32; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:26:58 +02:00
										 |  |  |   this->param_buffers.align = 16; | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   this->params[1] = &this->param_meta.param; | 
					
						
							|  |  |  |   this->param_meta.param.type = SPA_ALLOC_PARAM_TYPE_META_ENABLE; | 
					
						
							|  |  |  |   this->param_meta.param.size = sizeof (this->param_meta); | 
					
						
							|  |  |  |   this->param_meta.type = SPA_META_TYPE_HEADER; | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |   this->params[2] = &this->param_meta_rb.param; | 
					
						
							|  |  |  |   this->param_meta_rb.param.type = SPA_ALLOC_PARAM_TYPE_META_ENABLE; | 
					
						
							|  |  |  |   this->param_meta_rb.param.size = sizeof (this->param_meta_rb); | 
					
						
							|  |  |  |   this->param_meta_rb.type = SPA_META_TYPE_RINGBUFFER; | 
					
						
							|  |  |  |   this->param_meta_rb.minsize = this->period_frames * this->frame_size * 32; | 
					
						
							|  |  |  |   this->param_meta_rb.stride = 0; | 
					
						
							|  |  |  |   this->param_meta_rb.blocks = 1; | 
					
						
							|  |  |  |   this->param_meta_rb.align = 16; | 
					
						
							| 
									
										
										
										
											2016-10-14 10:42:02 +02:00
										 |  |  |   this->info.extra = NULL; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:26:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   this->have_format = true; | 
					
						
							| 
									
										
										
										
											2016-09-12 15:25:53 +02:00
										 |  |  |   update_state (this, SPA_NODE_STATE_READY); | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_port_get_format (SpaNode          *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                     SpaDirection      direction, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                     uint32_t          port_id, | 
					
						
							|  |  |  |                                     const SpaFormat **format) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL || format == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |   if (!CHECK_PORT (this, direction, port_id)) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!this->have_format) | 
					
						
							|  |  |  |     return SPA_RESULT_NO_FORMAT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *format = &this->current_format.format; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_port_get_info (SpaNode            *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                   SpaDirection        direction, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                   uint32_t            port_id, | 
					
						
							|  |  |  |                                   const SpaPortInfo **info) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL || info == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |   if (!CHECK_PORT (this, direction, port_id)) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *info = &this->info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  | spa_alsa_sink_node_port_get_props (SpaNode       *node, | 
					
						
							|  |  |  |                                    SpaDirection   direction, | 
					
						
							|  |  |  |                                    uint32_t       port_id, | 
					
						
							|  |  |  |                                    SpaProps     **props) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   return SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_port_set_props (SpaNode         *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                    SpaDirection     direction, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |                                    uint32_t         port_id, | 
					
						
							|  |  |  |                                    const SpaProps  *props) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_port_use_buffers (SpaNode         *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                      SpaDirection     direction, | 
					
						
							| 
									
										
										
										
											2016-07-08 20:12:56 +02:00
										 |  |  |                                      uint32_t         port_id, | 
					
						
							| 
									
										
										
										
											2016-07-11 17:45:54 +02:00
										 |  |  |                                      SpaBuffer      **buffers, | 
					
						
							| 
									
										
										
										
											2016-07-08 20:12:56 +02:00
										 |  |  |                                      uint32_t         n_buffers) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (node == NULL) | 
					
						
							|  |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!CHECK_PORT (this, direction, port_id)) | 
					
						
							|  |  |  |     return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |   spa_log_info (this->log, "use buffers %d", n_buffers); | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!this->have_format) | 
					
						
							|  |  |  |     return SPA_RESULT_NO_FORMAT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (n_buffers == 0) { | 
					
						
							|  |  |  |     spa_alsa_pause (this, false); | 
					
						
							|  |  |  |     spa_alsa_clear_buffers (this); | 
					
						
							|  |  |  |     update_state (this, SPA_NODE_STATE_READY); | 
					
						
							|  |  |  |     return SPA_RESULT_OK; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < n_buffers; i++) { | 
					
						
							|  |  |  |     SpaALSABuffer *b = &this->buffers[i]; | 
					
						
							|  |  |  |     b->outbuf = buffers[i]; | 
					
						
							|  |  |  |     b->outstanding = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     b->h = spa_buffer_find_meta (b->outbuf, SPA_META_TYPE_HEADER); | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |     b->rb = spa_buffer_find_meta (b->outbuf, SPA_META_TYPE_RINGBUFFER); | 
					
						
							|  |  |  |     if (b->rb) | 
					
						
							|  |  |  |       this->ringbuffer = b; | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (buffers[i]->datas[0].type) { | 
					
						
							|  |  |  |       case SPA_DATA_TYPE_MEMFD: | 
					
						
							|  |  |  |       case SPA_DATA_TYPE_DMABUF: | 
					
						
							|  |  |  |       case SPA_DATA_TYPE_MEMPTR: | 
					
						
							|  |  |  |         if (buffers[i]->datas[0].data == NULL) { | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |           spa_log_error (this->log, "alsa-source: need mapped memory"); | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |           continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   this->n_buffers = n_buffers; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   update_state (this, SPA_NODE_STATE_PAUSED); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							| 
									
										
										
										
											2016-07-08 20:12:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | spa_alsa_sink_node_port_alloc_buffers (SpaNode         *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                        SpaDirection     direction, | 
					
						
							| 
									
										
										
										
											2016-07-08 20:12:56 +02:00
										 |  |  |                                        uint32_t         port_id, | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  |                                        SpaAllocParam  **params, | 
					
						
							|  |  |  |                                        uint32_t         n_params, | 
					
						
							| 
									
										
										
										
											2016-07-08 20:12:56 +02:00
										 |  |  |                                        SpaBuffer      **buffers, | 
					
						
							|  |  |  |                                        uint32_t        *n_buffers) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-08-24 16:26:58 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL || buffers == NULL) | 
					
						
							| 
									
										
										
										
											2016-08-24 16:26:58 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |   if (!CHECK_PORT (this, direction, port_id)) | 
					
						
							| 
									
										
										
										
											2016-08-24 16:26:58 +02:00
										 |  |  |     return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:26:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!this->have_format) | 
					
						
							|  |  |  |     return SPA_RESULT_NO_FORMAT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 18:18:59 +02:00
										 |  |  |   return SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							| 
									
										
										
										
											2016-07-08 20:12:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 16:34:44 +02:00
										 |  |  | static SpaResult | 
					
						
							|  |  |  | spa_alsa_sink_node_port_get_status (SpaNode              *node, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |                                     SpaDirection          direction, | 
					
						
							| 
									
										
										
										
											2016-08-02 16:34:44 +02:00
										 |  |  |                                     uint32_t              port_id, | 
					
						
							|  |  |  |                                     const SpaPortStatus **status) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   SpaALSASink *this; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL || status == NULL) | 
					
						
							| 
									
										
										
										
											2016-08-02 16:34:44 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-08-02 16:34:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |   if (!CHECK_PORT (this, direction, port_id)) | 
					
						
							| 
									
										
										
										
											2016-08-02 16:34:44 +02:00
										 |  |  |     return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *status = &this->status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 20:12:56 +02:00
										 |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-09-06 16:43:37 +02:00
										 |  |  | spa_alsa_sink_node_port_push_input (SpaNode          *node, | 
					
						
							|  |  |  |                                     unsigned int      n_info, | 
					
						
							|  |  |  |                                     SpaPortInputInfo *info) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   unsigned int i; | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   bool have_error = false; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   if (node == NULL || n_info == 0 || info == NULL) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-12 17:27:29 +02:00
										 |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   for (i = 0; i < n_info; i++) { | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |     SpaALSABuffer *b; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     if (info[i].port_id != 0) { | 
					
						
							|  |  |  |       info[i].status = SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  |       have_error = true; | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |     if (!this->have_format) { | 
					
						
							|  |  |  |       info[i].status = SPA_RESULT_NO_FORMAT; | 
					
						
							|  |  |  |       have_error = true; | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |     if (info[i].buffer_id >= this->n_buffers) { | 
					
						
							|  |  |  |       info[i].status = SPA_RESULT_INVALID_BUFFER_ID; | 
					
						
							|  |  |  |       have_error = true; | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |     b = &this->buffers[info[i].buffer_id]; | 
					
						
							|  |  |  |     if (!b->outstanding) { | 
					
						
							|  |  |  |       info[i].status = SPA_RESULT_INVALID_BUFFER_ID; | 
					
						
							|  |  |  |       have_error = true; | 
					
						
							|  |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-11-03 19:41:53 +01:00
										 |  |  |     if (this->ringbuffer) { | 
					
						
							|  |  |  |       this->ringbuffer->outstanding = true; | 
					
						
							|  |  |  |       this->ringbuffer = b; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       b->next = NULL; | 
					
						
							|  |  |  |       SPA_QUEUE_PUSH_TAIL (&this->ready, SpaALSABuffer, next, b); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |     b->outstanding = false; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |     info[i].status = SPA_RESULT_OK; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (have_error) | 
					
						
							|  |  |  |     return SPA_RESULT_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-09-06 16:43:37 +02:00
										 |  |  | spa_alsa_sink_node_port_pull_output (SpaNode           *node, | 
					
						
							|  |  |  |                                      unsigned int       n_info, | 
					
						
							|  |  |  |                                      SpaPortOutputInfo *info) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  | static SpaResult | 
					
						
							|  |  |  | spa_alsa_sink_node_port_reuse_buffer (SpaNode         *node, | 
					
						
							|  |  |  |                                       uint32_t         port_id, | 
					
						
							|  |  |  |                                       uint32_t         buffer_id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							| 
									
										
										
										
											2016-10-21 14:57:01 +02:00
										 |  |  | spa_alsa_sink_node_port_send_command (SpaNode          *node, | 
					
						
							|  |  |  |                                       SpaDirection      direction, | 
					
						
							|  |  |  |                                       uint32_t          port_id, | 
					
						
							|  |  |  |                                       SpaNodeCommand   *command) | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							|  |  |  |   SpaResult res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (node == NULL) | 
					
						
							|  |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   this = SPA_CONTAINER_OF (node, SpaALSASink, node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (port_id != 0) | 
					
						
							|  |  |  |     return SPA_RESULT_INVALID_PORT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (command->type) { | 
					
						
							|  |  |  |     case SPA_NODE_COMMAND_PAUSE: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) { | 
					
						
							|  |  |  |         update_state (this, SPA_NODE_STATE_PAUSED); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case SPA_NODE_COMMAND_START: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) { | 
					
						
							|  |  |  |         update_state (this, SPA_NODE_STATE_STREAMING); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       res = SPA_RESULT_NOT_IMPLEMENTED; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return res; | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | static const SpaNode alsasink_node = { | 
					
						
							|  |  |  |   sizeof (SpaNode), | 
					
						
							| 
									
										
										
										
											2016-09-15 17:51:34 +02:00
										 |  |  |   NULL, | 
					
						
							| 
									
										
										
										
											2016-09-05 16:23:40 +02:00
										 |  |  |   SPA_NODE_STATE_INIT, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   spa_alsa_sink_node_get_props, | 
					
						
							|  |  |  |   spa_alsa_sink_node_set_props, | 
					
						
							|  |  |  |   spa_alsa_sink_node_send_command, | 
					
						
							|  |  |  |   spa_alsa_sink_node_set_event_callback, | 
					
						
							|  |  |  |   spa_alsa_sink_node_get_n_ports, | 
					
						
							|  |  |  |   spa_alsa_sink_node_get_port_ids, | 
					
						
							|  |  |  |   spa_alsa_sink_node_add_port, | 
					
						
							|  |  |  |   spa_alsa_sink_node_remove_port, | 
					
						
							| 
									
										
										
										
											2016-07-08 20:12:56 +02:00
										 |  |  |   spa_alsa_sink_node_port_enum_formats, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_set_format, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_get_format, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_get_info, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_get_props, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_set_props, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_use_buffers, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_alloc_buffers, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_get_status, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_push_input, | 
					
						
							|  |  |  |   spa_alsa_sink_node_port_pull_output, | 
					
						
							| 
									
										
										
										
											2016-10-03 19:43:42 +02:00
										 |  |  |   spa_alsa_sink_node_port_reuse_buffer, | 
					
						
							| 
									
										
										
										
											2016-10-21 14:57:01 +02:00
										 |  |  |   spa_alsa_sink_node_port_send_command, | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							|  |  |  | spa_alsa_sink_get_interface (SpaHandle               *handle, | 
					
						
							|  |  |  |                              uint32_t                 interface_id, | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |                              void                   **interface) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   SpaALSASink *this; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   if (handle == NULL || interface == NULL) | 
					
						
							|  |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   this = (SpaALSASink *) handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |   if (interface_id == this->uri.node) | 
					
						
							|  |  |  |     *interface = &this->node; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return SPA_RESULT_UNKNOWN_INTERFACE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-01 10:04:25 +02:00
										 |  |  | static SpaResult | 
					
						
							|  |  |  | alsa_sink_clear (SpaHandle *handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  | static SpaResult | 
					
						
							|  |  |  | alsa_sink_init (const SpaHandleFactory  *factory, | 
					
						
							| 
									
										
										
										
											2016-09-15 11:49:34 +02:00
										 |  |  |                 SpaHandle               *handle, | 
					
						
							| 
									
										
										
										
											2016-10-05 17:43:11 +02:00
										 |  |  |                 const SpaDict           *info, | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |                 const SpaSupport        *support, | 
					
						
							| 
									
										
										
										
											2016-10-05 21:05:22 +02:00
										 |  |  |                 unsigned int             n_support) | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   SpaALSASink *this; | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |   unsigned int i; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  |   if (factory == NULL || handle == NULL) | 
					
						
							|  |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  |   handle->get_interface = spa_alsa_sink_get_interface; | 
					
						
							| 
									
										
										
										
											2016-09-01 10:04:25 +02:00
										 |  |  |   handle->clear = alsa_sink_clear; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   this = (SpaALSASink *) handle; | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < n_support; i++) { | 
					
						
							|  |  |  |     if (strcmp (support[i].uri, SPA_ID_MAP_URI) == 0) | 
					
						
							|  |  |  |       this->map = support[i].data; | 
					
						
							|  |  |  |     else if (strcmp (support[i].uri, SPA_LOG_URI) == 0) | 
					
						
							|  |  |  |       this->log = support[i].data; | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |     else if (strcmp (support[i].uri, SPA_POLL__DataLoop) == 0) | 
					
						
							|  |  |  |       this->data_loop = support[i].data; | 
					
						
							|  |  |  |     else if (strcmp (support[i].uri, SPA_POLL__MainLoop) == 0) | 
					
						
							|  |  |  |       this->main_loop = support[i].data; | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (this->map == NULL) { | 
					
						
							|  |  |  |     spa_log_error (this->log, "an id-map is needed"); | 
					
						
							|  |  |  |     return SPA_RESULT_ERROR; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-30 20:35:34 +02:00
										 |  |  |   this->node = alsasink_node; | 
					
						
							| 
									
										
										
										
											2016-07-07 09:30:18 +02:00
										 |  |  |   this->props[1].props.n_prop_info = PROP_ID_LAST; | 
					
						
							|  |  |  |   this->props[1].props.prop_info = prop_info; | 
					
						
							| 
									
										
										
										
											2016-09-19 09:16:58 +02:00
										 |  |  |   this->stream = SND_PCM_STREAM_PLAYBACK; | 
					
						
							| 
									
										
										
										
											2016-07-07 09:30:18 +02:00
										 |  |  |   reset_alsa_sink_props (&this->props[1]); | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-28 16:56:33 +02:00
										 |  |  |   this->status.flags = SPA_PORT_STATUS_FLAG_NONE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; info && i < info->n_items; i++) { | 
					
						
							|  |  |  |     if (!strcmp (info->items[i].key, "alsa.card")) { | 
					
						
							|  |  |  |       snprintf (this->props[1].device, 63, "hw:%s", info->items[i].value); | 
					
						
							|  |  |  |       this->props[1].props.unset_mask &= ~1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-26 17:27:04 +02:00
										 |  |  |   update_state (this, SPA_NODE_STATE_CONFIGURE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  |   return SPA_RESULT_OK; | 
					
						
							| 
									
										
										
										
											2016-06-28 12:21:56 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static const SpaInterfaceInfo alsa_sink_interfaces[] = | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-07 13:14:32 +02:00
										 |  |  |   { SPA_NODE_URI, }, | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static SpaResult | 
					
						
							|  |  |  | alsa_sink_enum_interface_info (const SpaHandleFactory  *factory, | 
					
						
							| 
									
										
										
										
											2016-07-15 18:22:29 +02:00
										 |  |  |                                const SpaInterfaceInfo **info, | 
					
						
							|  |  |  |                                void                   **state) | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-15 18:22:29 +02:00
										 |  |  |   int index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (factory == NULL || info == NULL || state == NULL) | 
					
						
							|  |  |  |     return SPA_RESULT_INVALID_ARGUMENTS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   index = (*state == NULL ? 0 : *(int*)state); | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-15 18:22:29 +02:00
										 |  |  |   switch (index) { | 
					
						
							|  |  |  |     case 0: | 
					
						
							|  |  |  |       *info = &alsa_sink_interfaces[index]; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return SPA_RESULT_ENUM_END; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   *(int*)state = ++index; | 
					
						
							| 
									
										
										
										
											2016-07-13 18:29:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return SPA_RESULT_OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const SpaHandleFactory spa_alsa_sink_factory = | 
					
						
							|  |  |  | { "alsa-sink", | 
					
						
							|  |  |  |   NULL, | 
					
						
							|  |  |  |   sizeof (SpaALSASink), | 
					
						
							|  |  |  |   alsa_sink_init, | 
					
						
							|  |  |  |   alsa_sink_enum_interface_info, | 
					
						
							|  |  |  | }; |