2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
32 #include <pulse/timeval.h>
33 #include <pulse/version.h>
34 #include <pulse/utf8.h>
35 #include <pulse/util.h>
36 #include <pulse/xmalloc.h>
38 #include <pulsecore/native-common.h>
39 #include <pulsecore/packet.h>
40 #include <pulsecore/client.h>
41 #include <pulsecore/source-output.h>
42 #include <pulsecore/sink-input.h>
43 #include <pulsecore/pstream.h>
44 #include <pulsecore/tagstruct.h>
45 #include <pulsecore/pdispatch.h>
46 #include <pulsecore/pstream-util.h>
47 #include <pulsecore/authkey.h>
48 #include <pulsecore/namereg.h>
49 #include <pulsecore/core-scache.h>
50 #include <pulsecore/core-subscribe.h>
51 #include <pulsecore/log.h>
52 #include <pulsecore/strlist.h>
53 #include <pulsecore/shared.h>
54 #include <pulsecore/sample-util.h>
55 #include <pulsecore/llist.h>
56 #include <pulsecore/creds.h>
57 #include <pulsecore/core-util.h>
58 #include <pulsecore/ipacl.h>
59 #include <pulsecore/thread-mq.h>
61 #include "protocol-native.h"
63 /* Kick a client if it doesn't authenticate within this time */
64 #define AUTH_TIMEOUT 60
66 /* Don't accept more connection than this */
67 #define MAX_CONNECTIONS 64
69 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
70 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
71 #define DEFAULT_PROCESS_MSEC 20 /* 20ms */
72 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
74 struct pa_native_protocol;
76 typedef struct record_stream {
79 pa_native_connection *connection;
82 pa_source_output *source_output;
83 pa_memblockq *memblockq;
85 pa_bool_t adjust_latency:1;
86 pa_bool_t early_requests:1;
88 pa_buffer_attr buffer_attr;
90 pa_atomic_t on_the_fly;
91 pa_usec_t configured_source_latency;
94 /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
95 size_t on_the_fly_snapshot;
96 pa_usec_t current_monitor_latency;
97 pa_usec_t current_source_latency;
100 PA_DECLARE_CLASS(record_stream);
101 #define RECORD_STREAM(o) (record_stream_cast(o))
102 static PA_DEFINE_CHECK_TYPE(record_stream, pa_msgobject);
104 typedef struct output_stream {
108 PA_DECLARE_CLASS(output_stream);
109 #define OUTPUT_STREAM(o) (output_stream_cast(o))
110 static PA_DEFINE_CHECK_TYPE(output_stream, pa_msgobject);
112 typedef struct playback_stream {
113 output_stream parent;
115 pa_native_connection *connection;
118 pa_sink_input *sink_input;
119 pa_memblockq *memblockq;
121 pa_bool_t adjust_latency:1;
122 pa_bool_t early_requests:1;
124 pa_bool_t is_underrun:1;
125 pa_bool_t drain_request:1;
130 pa_usec_t configured_sink_latency;
131 pa_buffer_attr buffer_attr;
133 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
134 int64_t read_index, write_index;
135 size_t render_memblockq_length;
136 pa_usec_t current_sink_latency;
137 uint64_t playing_for, underrun_for;
140 PA_DECLARE_CLASS(playback_stream);
141 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
142 static PA_DEFINE_CHECK_TYPE(playback_stream, output_stream);
144 typedef struct upload_stream {
145 output_stream parent;
147 pa_native_connection *connection;
150 pa_memchunk memchunk;
153 pa_sample_spec sample_spec;
154 pa_channel_map channel_map;
155 pa_proplist *proplist;
158 PA_DECLARE_CLASS(upload_stream);
159 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
160 static PA_DEFINE_CHECK_TYPE(upload_stream, output_stream);
162 struct pa_native_connection {
164 pa_native_protocol *protocol;
165 pa_native_options *options;
166 pa_bool_t authorized:1;
167 pa_bool_t is_local:1;
171 pa_pdispatch *pdispatch;
172 pa_idxset *record_streams, *output_streams;
173 uint32_t rrobin_index;
174 pa_subscription *subscription;
175 pa_time_event *auth_timeout_event;
178 PA_DECLARE_CLASS(pa_native_connection);
179 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
180 static PA_DEFINE_CHECK_TYPE(pa_native_connection, pa_msgobject);
182 struct pa_native_protocol {
186 pa_idxset *connections;
189 pa_hook hooks[PA_NATIVE_HOOK_MAX];
191 pa_hashmap *extensions;
195 SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY = PA_SOURCE_OUTPUT_MESSAGE_MAX
199 SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
200 SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */
201 SINK_INPUT_MESSAGE_FLUSH,
202 SINK_INPUT_MESSAGE_TRIGGER,
203 SINK_INPUT_MESSAGE_SEEK,
204 SINK_INPUT_MESSAGE_PREBUF_FORCE,
205 SINK_INPUT_MESSAGE_UPDATE_LATENCY,
206 SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
210 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, /* data requested from sink input from the main loop */
211 PLAYBACK_STREAM_MESSAGE_UNDERFLOW,
212 PLAYBACK_STREAM_MESSAGE_OVERFLOW,
213 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK,
214 PLAYBACK_STREAM_MESSAGE_STARTED,
215 PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
219 RECORD_STREAM_MESSAGE_POST_DATA /* data from source output to main loop */
223 CONNECTION_MESSAGE_RELEASE,
224 CONNECTION_MESSAGE_REVOKE
227 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
228 static void sink_input_kill_cb(pa_sink_input *i);
229 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
230 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest);
231 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
232 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
233 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes);
234 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl);
236 static void native_connection_send_memblock(pa_native_connection *c);
237 static void playback_stream_request_bytes(struct playback_stream*s);
239 static void source_output_kill_cb(pa_source_output *o);
240 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
241 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend);
242 static void source_output_moving_cb(pa_source_output *o, pa_source *dest);
243 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
244 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl);
246 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
247 static int source_output_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
249 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
250 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
251 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
252 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
253 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
254 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
255 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
256 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
257 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
258 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
259 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
260 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
261 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
262 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
263 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
264 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
265 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
266 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
267 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
268 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
269 static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
270 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
271 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
272 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
273 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
274 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
275 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
276 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
277 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
278 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
279 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
280 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
281 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
282 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
283 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
284 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
285 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
286 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
288 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
289 [PA_COMMAND_ERROR] = NULL,
290 [PA_COMMAND_TIMEOUT] = NULL,
291 [PA_COMMAND_REPLY] = NULL,
292 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
293 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
294 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
295 [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
296 [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
297 [PA_COMMAND_AUTH] = command_auth,
298 [PA_COMMAND_REQUEST] = NULL,
299 [PA_COMMAND_EXIT] = command_exit,
300 [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
301 [PA_COMMAND_LOOKUP_SINK] = command_lookup,
302 [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
303 [PA_COMMAND_STAT] = command_stat,
304 [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
305 [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
306 [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
307 [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
308 [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
309 [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
310 [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
311 [PA_COMMAND_GET_SINK_INFO] = command_get_info,
312 [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
313 [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
314 [PA_COMMAND_GET_CARD_INFO] = command_get_info,
315 [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
316 [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
317 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
318 [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
319 [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
320 [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
321 [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
322 [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
323 [PA_COMMAND_GET_CARD_INFO_LIST] = command_get_info_list,
324 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
325 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
326 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
327 [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
328 [PA_COMMAND_SUBSCRIBE] = command_subscribe,
330 [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
331 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
332 [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
334 [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
335 [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
336 [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
338 [PA_COMMAND_SUSPEND_SINK] = command_suspend,
339 [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
341 [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
342 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
343 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
344 [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
346 [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
347 [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
349 [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
350 [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
351 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
352 [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
353 [PA_COMMAND_KILL_CLIENT] = command_kill,
354 [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
355 [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
356 [PA_COMMAND_LOAD_MODULE] = command_load_module,
357 [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
359 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE] = NULL,
360 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE] = NULL,
361 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE] = NULL,
362 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE] = NULL,
364 [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
365 [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream,
367 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
368 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
370 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
371 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
373 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = command_update_proplist,
374 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = command_update_proplist,
375 [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = command_update_proplist,
377 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = command_remove_proplist,
378 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
379 [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
381 [PA_COMMAND_SET_CARD_PROFILE] = command_set_card_profile,
383 [PA_COMMAND_EXTENSION] = command_extension
386 /* structure management */
388 /* Called from main context */
389 static void upload_stream_unlink(upload_stream *s) {
395 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
396 s->connection = NULL;
397 upload_stream_unref(s);
400 /* Called from main context */
401 static void upload_stream_free(pa_object *o) {
402 upload_stream *s = UPLOAD_STREAM(o);
405 upload_stream_unlink(s);
410 pa_proplist_free(s->proplist);
412 if (s->memchunk.memblock)
413 pa_memblock_unref(s->memchunk.memblock);
418 /* Called from main context */
419 static upload_stream* upload_stream_new(
420 pa_native_connection *c,
421 const pa_sample_spec *ss,
422 const pa_channel_map *map,
432 pa_assert(length > 0);
435 s = pa_msgobject_new(upload_stream);
436 s->parent.parent.parent.free = upload_stream_free;
438 s->sample_spec = *ss;
439 s->channel_map = *map;
440 s->name = pa_xstrdup(name);
441 pa_memchunk_reset(&s->memchunk);
443 s->proplist = pa_proplist_copy(p);
444 pa_proplist_update(s->proplist, PA_UPDATE_MERGE, c->client->proplist);
446 pa_idxset_put(c->output_streams, s, &s->index);
451 /* Called from main context */
452 static void record_stream_unlink(record_stream *s) {
458 if (s->source_output) {
459 pa_source_output_unlink(s->source_output);
460 pa_source_output_unref(s->source_output);
461 s->source_output = NULL;
464 pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
465 s->connection = NULL;
466 record_stream_unref(s);
469 /* Called from main context */
470 static void record_stream_free(pa_object *o) {
471 record_stream *s = RECORD_STREAM(o);
474 record_stream_unlink(s);
476 pa_memblockq_free(s->memblockq);
480 /* Called from main context */
481 static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
482 record_stream *s = RECORD_STREAM(o);
483 record_stream_assert_ref(s);
490 case RECORD_STREAM_MESSAGE_POST_DATA:
492 /* We try to keep up to date with how many bytes are
493 * currently on the fly */
494 pa_atomic_sub(&s->on_the_fly, chunk->length);
496 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
497 /* pa_log_warn("Failed to push data into output queue."); */
501 if (!pa_pstream_is_pending(s->connection->pstream))
502 native_connection_send_memblock(s->connection);
510 /* Called from main context */
511 static void fix_record_buffer_attr_pre(record_stream *s) {
514 pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec;
518 /* This function will be called from the main thread, before as
519 * well as after the source output has been activated using
520 * pa_source_output_put()! That means it may not touch any
521 * ->thread_info data! */
523 frame_size = pa_frame_size(&s->source_output->sample_spec);
525 if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
526 s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
527 if (s->buffer_attr.maxlength <= 0)
528 s->buffer_attr.maxlength = (uint32_t) frame_size;
530 if (s->buffer_attr.fragsize == (uint32_t) -1)
531 s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
532 if (s->buffer_attr.fragsize <= 0)
533 s->buffer_attr.fragsize = (uint32_t) frame_size;
535 orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(s->buffer_attr.fragsize, &s->source_output->sample_spec);
537 if (s->early_requests) {
539 /* In early request mode we need to emulate the classic
540 * fragment-based playback model. We do this setting the source
541 * latency to the fragment size. */
543 source_usec = fragsize_usec;
545 } else if (s->adjust_latency) {
547 /* So, the user asked us to adjust the latency according to
548 * what the source can provide. Half the latency will be
549 * spent on the hw buffer, half of it in the async buffer
550 * queue we maintain for each client. */
552 source_usec = fragsize_usec/2;
556 /* Ok, the user didn't ask us to adjust the latency, hence we
559 source_usec = (pa_usec_t) -1;
562 if (source_usec != (pa_usec_t) -1)
563 s->configured_source_latency = pa_source_output_set_requested_latency(s->source_output, source_usec);
565 s->configured_source_latency = 0;
567 if (s->early_requests) {
569 /* Ok, we didn't necessarily get what we were asking for, so
570 * let's tell the user */
572 fragsize_usec = s->configured_source_latency;
574 } else if (s->adjust_latency) {
576 /* Now subtract what we actually got */
578 if (fragsize_usec >= s->configured_source_latency*2)
579 fragsize_usec -= s->configured_source_latency;
581 fragsize_usec = s->configured_source_latency;
584 if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) !=
585 pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec))
587 s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
589 if (s->buffer_attr.fragsize <= 0)
590 s->buffer_attr.fragsize = (uint32_t) frame_size;
593 /* Called from main context */
594 static void fix_record_buffer_attr_post(record_stream *s) {
599 /* This function will be called from the main thread, before as
600 * well as after the source output has been activated using
601 * pa_source_output_put()! That means it may not touch and
602 * ->thread_info data! */
604 base = pa_frame_size(&s->source_output->sample_spec);
606 s->buffer_attr.fragsize = (s->buffer_attr.fragsize/base)*base;
607 if (s->buffer_attr.fragsize <= 0)
608 s->buffer_attr.fragsize = base;
610 if (s->buffer_attr.fragsize > s->buffer_attr.maxlength)
611 s->buffer_attr.fragsize = s->buffer_attr.maxlength;
614 /* Called from main context */
615 static record_stream* record_stream_new(
616 pa_native_connection *c,
620 pa_bool_t peak_detect,
621 pa_buffer_attr *attr,
622 pa_source_output_flags_t flags,
624 pa_bool_t adjust_latency,
625 pa_sink_input *direct_on_input,
626 pa_bool_t early_requests,
630 pa_source_output *source_output = NULL;
632 pa_source_output_new_data data;
639 pa_source_output_new_data_init(&data);
641 pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
642 data.driver = __FILE__;
643 data.module = c->options->module;
644 data.client = c->client;
645 data.source = source;
646 data.direct_on_input = direct_on_input;
647 pa_source_output_new_data_set_sample_spec(&data, ss);
648 pa_source_output_new_data_set_channel_map(&data, map);
650 data.resample_method = PA_RESAMPLER_PEAKS;
652 *ret = -pa_source_output_new(&source_output, c->protocol->core, &data, flags);
654 pa_source_output_new_data_done(&data);
659 s = pa_msgobject_new(record_stream);
660 s->parent.parent.free = record_stream_free;
661 s->parent.process_msg = record_stream_process_msg;
663 s->source_output = source_output;
664 s->buffer_attr = *attr;
665 s->adjust_latency = adjust_latency;
666 s->early_requests = early_requests;
667 pa_atomic_store(&s->on_the_fly, 0);
669 s->source_output->parent.process_msg = source_output_process_msg;
670 s->source_output->push = source_output_push_cb;
671 s->source_output->kill = source_output_kill_cb;
672 s->source_output->get_latency = source_output_get_latency_cb;
673 s->source_output->moving = source_output_moving_cb;
674 s->source_output->suspend = source_output_suspend_cb;
675 s->source_output->send_event = source_output_send_event_cb;
676 s->source_output->userdata = s;
678 fix_record_buffer_attr_pre(s);
680 s->memblockq = pa_memblockq_new(
682 s->buffer_attr.maxlength,
684 base = pa_frame_size(&source_output->sample_spec),
690 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
691 fix_record_buffer_attr_post(s);
693 *ss = s->source_output->sample_spec;
694 *map = s->source_output->channel_map;
696 pa_idxset_put(c->record_streams, s, &s->index);
698 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
699 ((double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) + (double) s->configured_source_latency) / PA_USEC_PER_MSEC,
700 (double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) / PA_USEC_PER_MSEC,
701 (double) s->configured_source_latency / PA_USEC_PER_MSEC);
703 pa_source_output_put(s->source_output);
707 /* Called from main context */
708 static void record_stream_send_killed(record_stream *r) {
710 record_stream_assert_ref(r);
712 t = pa_tagstruct_new(NULL, 0);
713 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
714 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
715 pa_tagstruct_putu32(t, r->index);
716 pa_pstream_send_tagstruct(r->connection->pstream, t);
719 /* Called from main context */
720 static void playback_stream_unlink(playback_stream *s) {
727 pa_sink_input_unlink(s->sink_input);
728 pa_sink_input_unref(s->sink_input);
729 s->sink_input = NULL;
732 if (s->drain_request)
733 pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
735 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
736 s->connection = NULL;
737 playback_stream_unref(s);
740 /* Called from main context */
741 static void playback_stream_free(pa_object* o) {
742 playback_stream *s = PLAYBACK_STREAM(o);
745 playback_stream_unlink(s);
747 pa_memblockq_free(s->memblockq);
751 /* Called from main context */
752 static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
753 playback_stream *s = PLAYBACK_STREAM(o);
754 playback_stream_assert_ref(s);
760 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
765 if ((l = pa_atomic_load(&s->missing)) <= 0)
768 if (pa_atomic_cmpxchg(&s->missing, l, 0))
772 t = pa_tagstruct_new(NULL, 0);
773 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
774 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
775 pa_tagstruct_putu32(t, s->index);
776 pa_tagstruct_putu32(t, (uint32_t) l);
777 pa_pstream_send_tagstruct(s->connection->pstream, t);
779 /* pa_log("Requesting %lu bytes", (unsigned long) l); */
783 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
786 /* pa_log("signalling underflow"); */
788 /* Report that we're empty */
789 t = pa_tagstruct_new(NULL, 0);
790 pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
791 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
792 pa_tagstruct_putu32(t, s->index);
793 pa_pstream_send_tagstruct(s->connection->pstream, t);
797 case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
800 /* Notify the user we're overflowed*/
801 t = pa_tagstruct_new(NULL, 0);
802 pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
803 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
804 pa_tagstruct_putu32(t, s->index);
805 pa_pstream_send_tagstruct(s->connection->pstream, t);
809 case PLAYBACK_STREAM_MESSAGE_STARTED:
811 if (s->connection->version >= 13) {
814 /* Notify the user we started playback */
815 t = pa_tagstruct_new(NULL, 0);
816 pa_tagstruct_putu32(t, PA_COMMAND_STARTED);
817 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
818 pa_tagstruct_putu32(t, s->index);
819 pa_pstream_send_tagstruct(s->connection->pstream, t);
824 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
825 pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
828 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH: {
831 s->buffer_attr.tlength = (uint32_t) offset;
833 t = pa_tagstruct_new(NULL, 0);
834 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
835 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
836 pa_tagstruct_putu32(t, s->index);
837 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
838 pa_tagstruct_putu32(t, s->buffer_attr.tlength);
839 pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
840 pa_tagstruct_putu32(t, s->buffer_attr.minreq);
841 pa_tagstruct_put_usec(t, s->configured_sink_latency);
842 pa_pstream_send_tagstruct(s->connection->pstream, t);
851 /* Called from main context */
852 static void fix_playback_buffer_attr(playback_stream *s) {
853 size_t frame_size, max_prebuf;
854 pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec;
858 /* This function will be called from the main thread, before as
859 * well as after the sink input has been activated using
860 * pa_sink_input_put()! That means it may not touch any
861 * ->thread_info data, such as the memblockq! */
863 frame_size = pa_frame_size(&s->sink_input->sample_spec);
865 if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
866 s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
867 if (s->buffer_attr.maxlength <= 0)
868 s->buffer_attr.maxlength = (uint32_t) frame_size;
870 if (s->buffer_attr.tlength == (uint32_t) -1)
871 s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
872 if (s->buffer_attr.tlength <= 0)
873 s->buffer_attr.tlength = (uint32_t) frame_size;
875 if (s->buffer_attr.minreq == (uint32_t) -1)
876 s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
877 if (s->buffer_attr.minreq <= 0)
878 s->buffer_attr.minreq = (uint32_t) frame_size;
880 if (s->buffer_attr.tlength < s->buffer_attr.minreq+frame_size)
881 s->buffer_attr.tlength = s->buffer_attr.minreq+(uint32_t) frame_size;
883 orig_tlength_usec = tlength_usec = pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec);
884 orig_minreq_usec = minreq_usec = pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec);
886 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
887 (double) tlength_usec / PA_USEC_PER_MSEC,
888 (double) minreq_usec / PA_USEC_PER_MSEC);
890 if (s->early_requests) {
892 /* In early request mode we need to emulate the classic
893 * fragment-based playback model. We do this setting the sink
894 * latency to the fragment size. */
896 sink_usec = minreq_usec;
897 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
899 } else if (s->adjust_latency) {
901 /* So, the user asked us to adjust the latency of the stream
902 * buffer according to the what the sink can provide. The
903 * tlength passed in shall be the overall latency. Roughly
904 * half the latency will be spent on the hw buffer, the other
905 * half of it in the async buffer queue we maintain for each
906 * client. In between we'll have a safety space of size
907 * 2*minreq. Why the 2*minreq? When the hw buffer is completey
908 * empty and needs to be filled, then our buffer must have
909 * enough data to fulfill this request immediatly and thus
910 * have at least the same tlength as the size of the hw
911 * buffer. It additionally needs space for 2 times minreq
912 * because if the buffer ran empty and a partial fillup
913 * happens immediately on the next iteration we need to be
914 * able to fulfill it and give the application also minreq
915 * time to fill it up again for the next request Makes 2 times
916 * minreq in plus.. */
918 if (tlength_usec > minreq_usec*2)
919 sink_usec = (tlength_usec - minreq_usec*2)/2;
923 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
927 /* Ok, the user didn't ask us to adjust the latency, but we
928 * still need to make sure that the parameters from the user
931 if (tlength_usec > minreq_usec*2)
932 sink_usec = (tlength_usec - minreq_usec*2);
936 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
939 s->configured_sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
941 if (s->early_requests) {
943 /* Ok, we didn't necessarily get what we were asking for, so
944 * let's tell the user */
946 minreq_usec = s->configured_sink_latency;
948 } else if (s->adjust_latency) {
950 /* Ok, we didn't necessarily get what we were asking for, so
951 * let's subtract from what we asked for for the remaining
954 if (tlength_usec >= s->configured_sink_latency)
955 tlength_usec -= s->configured_sink_latency;
958 /* FIXME: This is actually larger than necessary, since not all of
959 * the sink latency is actually rewritable. */
960 if (tlength_usec < s->configured_sink_latency + 2*minreq_usec)
961 tlength_usec = s->configured_sink_latency + 2*minreq_usec;
963 if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) !=
964 pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec))
965 s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec);
967 if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) !=
968 pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec))
969 s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
971 if (s->buffer_attr.minreq <= 0) {
972 s->buffer_attr.minreq = (uint32_t) frame_size;
973 s->buffer_attr.tlength += (uint32_t) frame_size*2;
976 if (s->buffer_attr.tlength <= s->buffer_attr.minreq)
977 s->buffer_attr.tlength = s->buffer_attr.minreq*2 + (uint32_t) frame_size;
979 max_prebuf = s->buffer_attr.tlength + (uint32_t)frame_size - s->buffer_attr.minreq;
981 if (s->buffer_attr.prebuf == (uint32_t) -1 ||
982 s->buffer_attr.prebuf > max_prebuf)
983 s->buffer_attr.prebuf = max_prebuf;
986 /* Called from main context */
987 static playback_stream* playback_stream_new(
988 pa_native_connection *c,
998 pa_sink_input_flags_t flags,
1000 pa_bool_t adjust_latency,
1001 pa_bool_t early_requests,
1004 playback_stream *s, *ssync;
1005 pa_sink_input *sink_input = NULL;
1006 pa_memchunk silence;
1008 int64_t start_index;
1009 pa_sink_input_new_data data;
1017 /* Find syncid group */
1018 for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
1020 if (!playback_stream_isinstance(ssync))
1023 if (ssync->syncid == syncid)
1027 /* Synced streams must connect to the same sink */
1031 sink = ssync->sink_input->sink;
1032 else if (sink != ssync->sink_input->sink) {
1033 *ret = PA_ERR_INVALID;
1038 pa_sink_input_new_data_init(&data);
1040 pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
1041 data.driver = __FILE__;
1042 data.module = c->options->module;
1043 data.client = c->client;
1045 pa_sink_input_new_data_set_sample_spec(&data, ss);
1046 pa_sink_input_new_data_set_channel_map(&data, map);
1048 pa_sink_input_new_data_set_volume(&data, volume);
1050 pa_sink_input_new_data_set_muted(&data, muted);
1051 data.sync_base = ssync ? ssync->sink_input : NULL;
1053 *ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data, flags);
1055 pa_sink_input_new_data_done(&data);
1060 s = pa_msgobject_new(playback_stream);
1061 s->parent.parent.parent.free = playback_stream_free;
1062 s->parent.parent.process_msg = playback_stream_process_msg;
1065 s->sink_input = sink_input;
1066 s->is_underrun = TRUE;
1067 s->drain_request = FALSE;
1068 pa_atomic_store(&s->missing, 0);
1069 s->buffer_attr = *a;
1070 s->adjust_latency = adjust_latency;
1071 s->early_requests = early_requests;
1073 s->sink_input->parent.process_msg = sink_input_process_msg;
1074 s->sink_input->pop = sink_input_pop_cb;
1075 s->sink_input->process_rewind = sink_input_process_rewind_cb;
1076 s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1077 s->sink_input->update_max_request = sink_input_update_max_request_cb;
1078 s->sink_input->kill = sink_input_kill_cb;
1079 s->sink_input->moving = sink_input_moving_cb;
1080 s->sink_input->suspend = sink_input_suspend_cb;
1081 s->sink_input->send_event = sink_input_send_event_cb;
1082 s->sink_input->userdata = s;
1084 start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
1086 fix_playback_buffer_attr(s);
1088 pa_sink_input_get_silence(sink_input, &silence);
1089 s->memblockq = pa_memblockq_new(
1091 s->buffer_attr.maxlength,
1092 s->buffer_attr.tlength,
1093 pa_frame_size(&sink_input->sample_spec),
1094 s->buffer_attr.prebuf,
1095 s->buffer_attr.minreq,
1098 pa_memblock_unref(silence.memblock);
1100 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1102 *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
1104 *ss = s->sink_input->sample_spec;
1105 *map = s->sink_input->channel_map;
1107 pa_idxset_put(c->output_streams, s, &s->index);
1109 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1110 ((double) pa_bytes_to_usec(s->buffer_attr.tlength, &sink_input->sample_spec) + (double) s->configured_sink_latency) / PA_USEC_PER_MSEC,
1111 (double) pa_bytes_to_usec(s->buffer_attr.tlength-s->buffer_attr.minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1112 (double) pa_bytes_to_usec(s->buffer_attr.minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1113 (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
1115 pa_sink_input_put(s->sink_input);
1119 /* Called from IO context */
1120 static void playback_stream_request_bytes(playback_stream *s) {
1122 int previous_missing;
1124 playback_stream_assert_ref(s);
1126 m = pa_memblockq_pop_missing(s->memblockq);
1131 /* pa_log("request_bytes(%lu)", (unsigned long) m); */
1133 previous_missing = pa_atomic_add(&s->missing, (int) m);
1134 minreq = pa_memblockq_get_minreq(s->memblockq);
1136 if (pa_memblockq_prebuf_active(s->memblockq) ||
1137 (previous_missing < (int) minreq && previous_missing + (int) m >= (int) minreq))
1138 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
1142 /* Called from main context */
1143 static void playback_stream_send_killed(playback_stream *p) {
1145 playback_stream_assert_ref(p);
1147 t = pa_tagstruct_new(NULL, 0);
1148 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
1149 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1150 pa_tagstruct_putu32(t, p->index);
1151 pa_pstream_send_tagstruct(p->connection->pstream, t);
1154 /* Called from main context */
1155 static int native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
1156 pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1157 pa_native_connection_assert_ref(c);
1164 case CONNECTION_MESSAGE_REVOKE:
1165 pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
1168 case CONNECTION_MESSAGE_RELEASE:
1169 pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
1176 /* Called from main context */
1177 static void native_connection_unlink(pa_native_connection *c) {
1186 pa_hook_fire(&c->protocol->hooks[PA_NATIVE_HOOK_CONNECTION_UNLINK], c);
1189 pa_native_options_unref(c->options);
1191 while ((r = pa_idxset_first(c->record_streams, NULL)))
1192 record_stream_unlink(r);
1194 while ((o = pa_idxset_first(c->output_streams, NULL)))
1195 if (playback_stream_isinstance(o))
1196 playback_stream_unlink(PLAYBACK_STREAM(o));
1198 upload_stream_unlink(UPLOAD_STREAM(o));
1200 if (c->subscription)
1201 pa_subscription_free(c->subscription);
1204 pa_pstream_unlink(c->pstream);
1206 if (c->auth_timeout_event) {
1207 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
1208 c->auth_timeout_event = NULL;
1211 pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
1213 pa_native_connection_unref(c);
1216 /* Called from main context */
1217 static void native_connection_free(pa_object *o) {
1218 pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1222 native_connection_unlink(c);
1224 pa_idxset_free(c->record_streams, NULL, NULL);
1225 pa_idxset_free(c->output_streams, NULL, NULL);
1227 pa_pdispatch_unref(c->pdispatch);
1228 pa_pstream_unref(c->pstream);
1229 pa_client_free(c->client);
1234 /* Called from main context */
1235 static void native_connection_send_memblock(pa_native_connection *c) {
1239 start = PA_IDXSET_INVALID;
1243 if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
1246 if (start == PA_IDXSET_INVALID)
1247 start = c->rrobin_index;
1248 else if (start == c->rrobin_index)
1251 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
1252 pa_memchunk schunk = chunk;
1254 if (schunk.length > r->buffer_attr.fragsize)
1255 schunk.length = r->buffer_attr.fragsize;
1257 pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
1259 pa_memblockq_drop(r->memblockq, schunk.length);
1260 pa_memblock_unref(schunk.memblock);
1267 /*** sink input callbacks ***/
1269 /* Called from thread context */
1270 static void handle_seek(playback_stream *s, int64_t indexw) {
1271 playback_stream_assert_ref(s);
1273 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1275 if (s->sink_input->thread_info.underrun_for > 0) {
1277 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1279 if (pa_memblockq_is_readable(s->memblockq)) {
1281 /* We just ended an underrun, let's ask the sink
1282 * for a complete rewind rewrite */
1284 pa_log_debug("Requesting rewind due to end of underrun.");
1285 pa_sink_input_request_rewind(s->sink_input,
1286 (size_t) (s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for),
1287 FALSE, TRUE, FALSE);
1293 indexr = pa_memblockq_get_read_index(s->memblockq);
1295 if (indexw < indexr) {
1296 /* OK, the sink already asked for this data, so
1297 * let's have it usk us again */
1299 pa_log_debug("Requesting rewind due to rewrite.");
1300 pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE, FALSE);
1304 playback_stream_request_bytes(s);
1307 /* Called from thread context */
1308 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1309 pa_sink_input *i = PA_SINK_INPUT(o);
1312 pa_sink_input_assert_ref(i);
1313 s = PLAYBACK_STREAM(i->userdata);
1314 playback_stream_assert_ref(s);
1318 case SINK_INPUT_MESSAGE_SEEK: {
1321 windex = pa_memblockq_get_write_index(s->memblockq);
1323 /* The client side is incapable of accounting correctly
1324 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1325 * able to deal with that. */
1327 pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata), PA_PTR_TO_UINT(userdata) == PA_SEEK_RELATIVE);
1329 handle_seek(s, windex);
1333 case SINK_INPUT_MESSAGE_POST_DATA: {
1338 windex = pa_memblockq_get_write_index(s->memblockq);
1340 /* pa_log("sink input post: %lu %lli", (unsigned long) chunk->length, (long long) windex); */
1342 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
1343 pa_log_warn("Failed to push data into queue");
1344 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
1345 pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, TRUE);
1348 handle_seek(s, windex);
1350 /* pa_log("sink input post2: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1355 case SINK_INPUT_MESSAGE_DRAIN:
1356 case SINK_INPUT_MESSAGE_FLUSH:
1357 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1358 case SINK_INPUT_MESSAGE_TRIGGER: {
1361 pa_sink_input *isync;
1362 void (*func)(pa_memblockq *bq);
1365 case SINK_INPUT_MESSAGE_FLUSH:
1366 func = pa_memblockq_flush_write;
1369 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1370 func = pa_memblockq_prebuf_force;
1373 case SINK_INPUT_MESSAGE_DRAIN:
1374 case SINK_INPUT_MESSAGE_TRIGGER:
1375 func = pa_memblockq_prebuf_disable;
1379 pa_assert_not_reached();
1382 windex = pa_memblockq_get_write_index(s->memblockq);
1384 handle_seek(s, windex);
1386 /* Do the same for all other members in the sync group */
1387 for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
1388 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1389 windex = pa_memblockq_get_write_index(ssync->memblockq);
1390 func(ssync->memblockq);
1391 handle_seek(ssync, windex);
1394 for (isync = i->sync_next; isync; isync = isync->sync_next) {
1395 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1396 windex = pa_memblockq_get_write_index(ssync->memblockq);
1397 func(ssync->memblockq);
1398 handle_seek(ssync, windex);
1401 if (code == SINK_INPUT_MESSAGE_DRAIN) {
1402 if (!pa_memblockq_is_readable(s->memblockq))
1403 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
1405 s->drain_tag = PA_PTR_TO_UINT(userdata);
1406 s->drain_request = TRUE;
1413 case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
1414 /* Atomically get a snapshot of all timing parameters... */
1415 s->read_index = pa_memblockq_get_read_index(s->memblockq);
1416 s->write_index = pa_memblockq_get_write_index(s->memblockq);
1417 s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
1418 s->current_sink_latency = pa_sink_get_latency_within_thread(s->sink_input->sink);
1419 s->underrun_for = s->sink_input->thread_info.underrun_for;
1420 s->playing_for = s->sink_input->thread_info.playing_for;
1424 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1427 windex = pa_memblockq_get_write_index(s->memblockq);
1429 pa_memblockq_prebuf_force(s->memblockq);
1431 handle_seek(s, windex);
1433 /* Fall through to the default handler */
1437 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1438 pa_usec_t *r = userdata;
1440 *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
1442 /* Fall through, the default handler will add in the extra
1443 * latency added by the resampler */
1447 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR: {
1448 pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1449 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1454 return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1457 /* Called from thread context */
1458 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
1461 pa_sink_input_assert_ref(i);
1462 s = PLAYBACK_STREAM(i->userdata);
1463 playback_stream_assert_ref(s);
1466 /* pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1468 if (pa_memblockq_is_readable(s->memblockq))
1469 s->is_underrun = FALSE;
1471 if (!s->is_underrun)
1472 pa_log_debug("Underrun on '%s', %lu bytes in queue.", pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)), (unsigned long) pa_memblockq_get_length(s->memblockq));
1474 if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
1475 s->drain_request = FALSE;
1476 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL);
1477 } else if (!s->is_underrun)
1478 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
1480 s->is_underrun = TRUE;
1482 playback_stream_request_bytes(s);
1485 /* This call will not fail with prebuf=0, hence we check for
1486 underrun explicitly above */
1487 if (pa_memblockq_peek(s->memblockq, chunk) < 0)
1490 chunk->length = PA_MIN(nbytes, chunk->length);
1492 if (i->thread_info.underrun_for > 0)
1493 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
1495 pa_memblockq_drop(s->memblockq, chunk->length);
1496 playback_stream_request_bytes(s);
1501 /* Called from thread context */
1502 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1505 pa_sink_input_assert_ref(i);
1506 s = PLAYBACK_STREAM(i->userdata);
1507 playback_stream_assert_ref(s);
1509 /* If we are in an underrun, then we don't rewind */
1510 if (i->thread_info.underrun_for > 0)
1513 pa_memblockq_rewind(s->memblockq, nbytes);
1516 /* Called from thread context */
1517 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1520 pa_sink_input_assert_ref(i);
1521 s = PLAYBACK_STREAM(i->userdata);
1522 playback_stream_assert_ref(s);
1524 pa_memblockq_set_maxrewind(s->memblockq, nbytes);
1527 /* Called from thread context */
1528 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
1530 size_t new_tlength, old_tlength;
1532 pa_sink_input_assert_ref(i);
1533 s = PLAYBACK_STREAM(i->userdata);
1534 playback_stream_assert_ref(s);
1536 old_tlength = pa_memblockq_get_tlength(s->memblockq);
1537 new_tlength = nbytes+2*pa_memblockq_get_minreq(s->memblockq);
1539 if (old_tlength < new_tlength) {
1540 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength, new_tlength);
1541 pa_memblockq_set_tlength(s->memblockq, new_tlength);
1542 new_tlength = pa_memblockq_get_tlength(s->memblockq);
1544 if (new_tlength == old_tlength)
1545 pa_log_debug("Failed to increase tlength");
1547 pa_log_debug("Notifying client about increased tlength");
1548 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH, NULL, pa_memblockq_get_tlength(s->memblockq), NULL, NULL);
1553 /* Called from main context */
1554 static void sink_input_kill_cb(pa_sink_input *i) {
1557 pa_sink_input_assert_ref(i);
1558 s = PLAYBACK_STREAM(i->userdata);
1559 playback_stream_assert_ref(s);
1561 playback_stream_send_killed(s);
1562 playback_stream_unlink(s);
1565 /* Called from main context */
1566 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl) {
1570 pa_sink_input_assert_ref(i);
1571 s = PLAYBACK_STREAM(i->userdata);
1572 playback_stream_assert_ref(s);
1574 if (s->connection->version < 15)
1577 t = pa_tagstruct_new(NULL, 0);
1578 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_EVENT);
1579 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1580 pa_tagstruct_putu32(t, s->index);
1581 pa_tagstruct_puts(t, event);
1582 pa_tagstruct_put_proplist(t, pl);
1583 pa_pstream_send_tagstruct(s->connection->pstream, t);
1586 /* Called from main context */
1587 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
1591 pa_sink_input_assert_ref(i);
1592 s = PLAYBACK_STREAM(i->userdata);
1593 playback_stream_assert_ref(s);
1595 if (s->connection->version < 12)
1598 t = pa_tagstruct_new(NULL, 0);
1599 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED);
1600 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1601 pa_tagstruct_putu32(t, s->index);
1602 pa_tagstruct_put_boolean(t, suspend);
1603 pa_pstream_send_tagstruct(s->connection->pstream, t);
1606 /* Called from main context */
1607 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1611 pa_sink_input_assert_ref(i);
1612 s = PLAYBACK_STREAM(i->userdata);
1613 playback_stream_assert_ref(s);
1615 fix_playback_buffer_attr(s);
1616 pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1617 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1619 if (s->connection->version < 12)
1622 t = pa_tagstruct_new(NULL, 0);
1623 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED);
1624 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1625 pa_tagstruct_putu32(t, s->index);
1626 pa_tagstruct_putu32(t, dest->index);
1627 pa_tagstruct_puts(t, dest->name);
1628 pa_tagstruct_put_boolean(t, pa_sink_get_state(dest) == PA_SINK_SUSPENDED);
1630 if (s->connection->version >= 13) {
1631 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1632 pa_tagstruct_putu32(t, s->buffer_attr.tlength);
1633 pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
1634 pa_tagstruct_putu32(t, s->buffer_attr.minreq);
1635 pa_tagstruct_put_usec(t, s->configured_sink_latency);
1638 pa_pstream_send_tagstruct(s->connection->pstream, t);
1641 /*** source_output callbacks ***/
1643 /* Called from thread context */
1644 static int source_output_process_msg(pa_msgobject *_o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1645 pa_source_output *o = PA_SOURCE_OUTPUT(_o);
1648 pa_source_output_assert_ref(o);
1649 s = RECORD_STREAM(o->userdata);
1650 record_stream_assert_ref(s);
1653 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY:
1654 /* Atomically get a snapshot of all timing parameters... */
1655 s->current_monitor_latency = o->source->monitor_of ? pa_sink_get_latency_within_thread(o->source->monitor_of) : 0;
1656 s->current_source_latency = pa_source_get_latency_within_thread(o->source);
1657 s->on_the_fly_snapshot = pa_atomic_load(&s->on_the_fly);
1661 return pa_source_output_process_msg(_o, code, userdata, offset, chunk);
1664 /* Called from thread context */
1665 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1668 pa_source_output_assert_ref(o);
1669 s = RECORD_STREAM(o->userdata);
1670 record_stream_assert_ref(s);
1673 pa_atomic_add(&s->on_the_fly, chunk->length);
1674 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1677 static void source_output_kill_cb(pa_source_output *o) {
1680 pa_source_output_assert_ref(o);
1681 s = RECORD_STREAM(o->userdata);
1682 record_stream_assert_ref(s);
1684 record_stream_send_killed(s);
1685 record_stream_unlink(s);
1688 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1691 pa_source_output_assert_ref(o);
1692 s = RECORD_STREAM(o->userdata);
1693 record_stream_assert_ref(s);
1695 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1697 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
1700 /* Called from main context */
1701 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl) {
1705 pa_source_output_assert_ref(o);
1706 s = RECORD_STREAM(o->userdata);
1707 record_stream_assert_ref(s);
1709 if (s->connection->version < 15)
1712 t = pa_tagstruct_new(NULL, 0);
1713 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_EVENT);
1714 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1715 pa_tagstruct_putu32(t, s->index);
1716 pa_tagstruct_puts(t, event);
1717 pa_tagstruct_put_proplist(t, pl);
1718 pa_pstream_send_tagstruct(s->connection->pstream, t);
1721 /* Called from main context */
1722 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
1726 pa_source_output_assert_ref(o);
1727 s = RECORD_STREAM(o->userdata);
1728 record_stream_assert_ref(s);
1730 if (s->connection->version < 12)
1733 t = pa_tagstruct_new(NULL, 0);
1734 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED);
1735 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1736 pa_tagstruct_putu32(t, s->index);
1737 pa_tagstruct_put_boolean(t, suspend);
1738 pa_pstream_send_tagstruct(s->connection->pstream, t);
1741 /* Called from main context */
1742 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
1746 pa_source_output_assert_ref(o);
1747 s = RECORD_STREAM(o->userdata);
1748 record_stream_assert_ref(s);
1750 fix_record_buffer_attr_pre(s);
1751 pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
1752 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1753 fix_record_buffer_attr_post(s);
1755 if (s->connection->version < 12)
1758 t = pa_tagstruct_new(NULL, 0);
1759 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED);
1760 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1761 pa_tagstruct_putu32(t, s->index);
1762 pa_tagstruct_putu32(t, dest->index);
1763 pa_tagstruct_puts(t, dest->name);
1764 pa_tagstruct_put_boolean(t, pa_source_get_state(dest) == PA_SOURCE_SUSPENDED);
1766 if (s->connection->version >= 13) {
1767 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1768 pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
1769 pa_tagstruct_put_usec(t, s->configured_source_latency);
1772 pa_pstream_send_tagstruct(s->connection->pstream, t);
1775 /*** pdispatch callbacks ***/
1777 static void protocol_error(pa_native_connection *c) {
1778 pa_log("protocol error, kicking client");
1779 native_connection_unlink(c);
1782 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1783 if (!(expression)) { \
1784 pa_pstream_send_error((pstream), (tag), (error)); \
1789 static pa_tagstruct *reply_new(uint32_t tag) {
1790 pa_tagstruct *reply;
1792 reply = pa_tagstruct_new(NULL, 0);
1793 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1794 pa_tagstruct_putu32(reply, tag);
1798 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1799 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
1801 uint32_t sink_index, syncid, missing;
1802 pa_buffer_attr attr;
1803 const char *name = NULL, *sink_name;
1806 pa_tagstruct *reply;
1807 pa_sink *sink = NULL;
1815 fix_channels = FALSE,
1817 variable_rate = FALSE,
1819 adjust_latency = FALSE,
1820 early_requests = FALSE,
1821 dont_inhibit_auto_suspend = FALSE,
1823 fail_on_suspend = FALSE;
1824 pa_sink_input_flags_t flags = 0;
1826 pa_bool_t volume_set = TRUE;
1827 int ret = PA_ERR_INVALID;
1829 pa_native_connection_assert_ref(c);
1831 memset(&attr, 0, sizeof(attr));
1833 if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
1836 PA_TAG_SAMPLE_SPEC, &ss,
1837 PA_TAG_CHANNEL_MAP, &map,
1838 PA_TAG_U32, &sink_index,
1839 PA_TAG_STRING, &sink_name,
1840 PA_TAG_U32, &attr.maxlength,
1841 PA_TAG_BOOLEAN, &corked,
1842 PA_TAG_U32, &attr.tlength,
1843 PA_TAG_U32, &attr.prebuf,
1844 PA_TAG_U32, &attr.minreq,
1845 PA_TAG_U32, &syncid,
1846 PA_TAG_CVOLUME, &volume,
1847 PA_TAG_INVALID) < 0) {
1853 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1854 CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name(sink_name), tag, PA_ERR_INVALID);
1855 CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
1856 CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
1857 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1858 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1859 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
1860 CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
1862 p = pa_proplist_new();
1865 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
1867 if (c->version >= 12) {
1868 /* Since 0.9.8 the user can ask for a couple of additional flags */
1870 if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
1871 pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
1872 pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
1873 pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
1874 pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
1875 pa_tagstruct_get_boolean(t, &no_move) < 0 ||
1876 pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
1879 pa_proplist_free(p);
1884 if (c->version >= 13) {
1886 if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
1887 pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
1888 pa_tagstruct_get_proplist(t, p) < 0) {
1890 pa_proplist_free(p);
1895 if (c->version >= 14) {
1897 if (pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
1898 pa_tagstruct_get_boolean(t, &early_requests) < 0) {
1900 pa_proplist_free(p);
1905 if (c->version >= 15) {
1907 if (pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
1908 pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
1909 pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
1911 pa_proplist_free(p);
1916 if (!pa_tagstruct_eof(t)) {
1918 pa_proplist_free(p);
1922 if (sink_index != PA_INVALID_INDEX) {
1924 if (!(sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index))) {
1925 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1926 pa_proplist_free(p);
1930 } else if (sink_name) {
1932 if (!(sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK))) {
1933 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1934 pa_proplist_free(p);
1940 (corked ? PA_SINK_INPUT_START_CORKED : 0) |
1941 (no_remap ? PA_SINK_INPUT_NO_REMAP : 0) |
1942 (no_remix ? PA_SINK_INPUT_NO_REMIX : 0) |
1943 (fix_format ? PA_SINK_INPUT_FIX_FORMAT : 0) |
1944 (fix_rate ? PA_SINK_INPUT_FIX_RATE : 0) |
1945 (fix_channels ? PA_SINK_INPUT_FIX_CHANNELS : 0) |
1946 (no_move ? PA_SINK_INPUT_DONT_MOVE : 0) |
1947 (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0) |
1948 (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
1949 (fail_on_suspend ? PA_SINK_INPUT_FAIL_ON_SUSPEND : 0);
1951 /* Only since protocol version 15 there's a seperate muted_set
1952 * flag. For older versions we synthesize it here */
1953 muted_set = muted_set || muted;
1955 s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
1956 pa_proplist_free(p);
1958 CHECK_VALIDITY(c->pstream, s, tag, ret);
1960 reply = reply_new(tag);
1961 pa_tagstruct_putu32(reply, s->index);
1962 pa_assert(s->sink_input);
1963 pa_tagstruct_putu32(reply, s->sink_input->index);
1964 pa_tagstruct_putu32(reply, missing);
1966 /* pa_log("initial request is %u", missing); */
1968 if (c->version >= 9) {
1969 /* Since 0.9.0 we support sending the buffer metrics back to the client */
1971 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
1972 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.tlength);
1973 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.prebuf);
1974 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.minreq);
1977 if (c->version >= 12) {
1978 /* Since 0.9.8 we support sending the chosen sample
1979 * spec/channel map/device/suspend status back to the
1982 pa_tagstruct_put_sample_spec(reply, &ss);
1983 pa_tagstruct_put_channel_map(reply, &map);
1985 pa_tagstruct_putu32(reply, s->sink_input->sink->index);
1986 pa_tagstruct_puts(reply, s->sink_input->sink->name);
1988 pa_tagstruct_put_boolean(reply, pa_sink_get_state(s->sink_input->sink) == PA_SINK_SUSPENDED);
1991 if (c->version >= 13)
1992 pa_tagstruct_put_usec(reply, s->configured_sink_latency);
1994 pa_pstream_send_tagstruct(c->pstream, reply);
1997 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1998 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2001 pa_native_connection_assert_ref(c);
2004 if (pa_tagstruct_getu32(t, &channel) < 0 ||
2005 !pa_tagstruct_eof(t)) {
2010 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2014 case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
2016 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
2017 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2021 playback_stream_unlink(s);
2025 case PA_COMMAND_DELETE_RECORD_STREAM: {
2027 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
2028 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2032 record_stream_unlink(s);
2036 case PA_COMMAND_DELETE_UPLOAD_STREAM: {
2039 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
2040 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2044 upload_stream_unlink(s);
2049 pa_assert_not_reached();
2052 pa_pstream_send_simple_ack(c->pstream, tag);
2055 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2056 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2058 pa_buffer_attr attr;
2059 uint32_t source_index;
2060 const char *name = NULL, *source_name;
2063 pa_tagstruct *reply;
2064 pa_source *source = NULL;
2071 fix_channels = FALSE,
2073 variable_rate = FALSE,
2074 adjust_latency = FALSE,
2075 peak_detect = FALSE,
2076 early_requests = FALSE,
2077 dont_inhibit_auto_suspend = FALSE,
2078 fail_on_suspend = FALSE;
2079 pa_source_output_flags_t flags = 0;
2081 uint32_t direct_on_input_idx = PA_INVALID_INDEX;
2082 pa_sink_input *direct_on_input = NULL;
2083 int ret = PA_ERR_INVALID;
2085 pa_native_connection_assert_ref(c);
2088 memset(&attr, 0, sizeof(attr));
2090 if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
2091 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2092 pa_tagstruct_get_channel_map(t, &map) < 0 ||
2093 pa_tagstruct_getu32(t, &source_index) < 0 ||
2094 pa_tagstruct_gets(t, &source_name) < 0 ||
2095 pa_tagstruct_getu32(t, &attr.maxlength) < 0 ||
2096 pa_tagstruct_get_boolean(t, &corked) < 0 ||
2097 pa_tagstruct_getu32(t, &attr.fragsize) < 0) {
2102 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2103 CHECK_VALIDITY(c->pstream, !source_name || pa_namereg_is_valid_name(source_name), tag, PA_ERR_INVALID);
2104 CHECK_VALIDITY(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID);
2105 CHECK_VALIDITY(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2106 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2107 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2108 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2110 p = pa_proplist_new();
2113 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2115 if (c->version >= 12) {
2116 /* Since 0.9.8 the user can ask for a couple of additional flags */
2118 if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
2119 pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
2120 pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
2121 pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
2122 pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
2123 pa_tagstruct_get_boolean(t, &no_move) < 0 ||
2124 pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
2127 pa_proplist_free(p);
2132 if (c->version >= 13) {
2134 if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
2135 pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
2136 pa_tagstruct_get_proplist(t, p) < 0 ||
2137 pa_tagstruct_getu32(t, &direct_on_input_idx) < 0) {
2139 pa_proplist_free(p);
2144 if (c->version >= 14) {
2146 if (pa_tagstruct_get_boolean(t, &early_requests) < 0) {
2148 pa_proplist_free(p);
2153 if (c->version >= 15) {
2155 if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
2156 pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
2158 pa_proplist_free(p);
2163 if (!pa_tagstruct_eof(t)) {
2165 pa_proplist_free(p);
2169 if (source_index != PA_INVALID_INDEX) {
2171 if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
2172 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2173 pa_proplist_free(p);
2177 } else if (source_name) {
2179 if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE))) {
2180 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2181 pa_proplist_free(p);
2186 if (direct_on_input_idx != PA_INVALID_INDEX) {
2188 if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
2189 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2190 pa_proplist_free(p);
2196 (corked ? PA_SOURCE_OUTPUT_START_CORKED : 0) |
2197 (no_remap ? PA_SOURCE_OUTPUT_NO_REMAP : 0) |
2198 (no_remix ? PA_SOURCE_OUTPUT_NO_REMIX : 0) |
2199 (fix_format ? PA_SOURCE_OUTPUT_FIX_FORMAT : 0) |
2200 (fix_rate ? PA_SOURCE_OUTPUT_FIX_RATE : 0) |
2201 (fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
2202 (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
2203 (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
2204 (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2205 (fail_on_suspend ? PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND : 0);
2207 s = record_stream_new(c, source, &ss, &map, peak_detect, &attr, flags, p, adjust_latency, direct_on_input, early_requests, &ret);
2208 pa_proplist_free(p);
2210 CHECK_VALIDITY(c->pstream, s, tag, ret);
2212 reply = reply_new(tag);
2213 pa_tagstruct_putu32(reply, s->index);
2214 pa_assert(s->source_output);
2215 pa_tagstruct_putu32(reply, s->source_output->index);
2217 if (c->version >= 9) {
2218 /* Since 0.9 we support sending the buffer metrics back to the client */
2220 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2221 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.fragsize);
2224 if (c->version >= 12) {
2225 /* Since 0.9.8 we support sending the chosen sample
2226 * spec/channel map/device/suspend status back to the
2229 pa_tagstruct_put_sample_spec(reply, &ss);
2230 pa_tagstruct_put_channel_map(reply, &map);
2232 pa_tagstruct_putu32(reply, s->source_output->source->index);
2233 pa_tagstruct_puts(reply, s->source_output->source->name);
2235 pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED);
2238 if (c->version >= 13)
2239 pa_tagstruct_put_usec(reply, s->configured_source_latency);
2241 pa_pstream_send_tagstruct(c->pstream, reply);
2244 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2245 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2248 pa_native_connection_assert_ref(c);
2251 if (!pa_tagstruct_eof(t)) {
2256 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2257 ret = pa_core_exit(c->protocol->core, FALSE, 0);
2258 CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
2260 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
2263 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2264 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2266 pa_tagstruct *reply;
2267 pa_bool_t shm_on_remote = FALSE, do_shm;
2269 pa_native_connection_assert_ref(c);
2272 if (pa_tagstruct_getu32(t, &c->version) < 0 ||
2273 pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
2274 !pa_tagstruct_eof(t)) {
2279 /* Minimum supported version */
2280 if (c->version < 8) {
2281 pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
2285 /* Starting with protocol version 13 the MSB of the version tag
2286 reflects if shm is available for this pa_native_connection or
2288 if (c->version >= 13) {
2289 shm_on_remote = !!(c->version & 0x80000000U);
2290 c->version &= 0x7FFFFFFFU;
2293 pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
2295 pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
2297 if (!c->authorized) {
2298 pa_bool_t success = FALSE;
2301 const pa_creds *creds;
2303 if ((creds = pa_pdispatch_creds(pd))) {
2304 if (creds->uid == getuid())
2306 else if (c->options->auth_group) {
2310 if ((gid = pa_get_gid_of_group(c->options->auth_group)) == (gid_t) -1)
2311 pa_log_warn("Failed to get GID of group '%s'", c->options->auth_group);
2312 else if (gid == creds->gid)
2316 if ((r = pa_uid_in_group(creds->uid, c->options->auth_group)) < 0)
2317 pa_log_warn("Failed to check group membership.");
2323 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2324 (unsigned long) creds->uid,
2325 (unsigned long) creds->gid,
2330 if (!success && c->options->auth_cookie) {
2333 if ((ac = pa_auth_cookie_read(c->options->auth_cookie, PA_NATIVE_COOKIE_LENGTH)))
2334 if (memcmp(ac, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
2339 pa_log_warn("Denied access to client with invalid authorization data.");
2340 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2344 c->authorized = TRUE;
2345 if (c->auth_timeout_event) {
2346 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
2347 c->auth_timeout_event = NULL;
2351 /* Enable shared memory support if possible */
2353 pa_mempool_is_shared(c->protocol->core->mempool) &&
2356 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm));
2359 if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
2364 /* Only enable SHM if both sides are owned by the same
2365 * user. This is a security measure because otherwise data
2366 * private to the user might leak. */
2368 const pa_creds *creds;
2369 if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
2374 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
2375 pa_pstream_enable_shm(c->pstream, do_shm);
2377 reply = reply_new(tag);
2378 pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0));
2382 /* SHM support is only enabled after both sides made sure they are the same user. */
2386 ucred.uid = getuid();
2387 ucred.gid = getgid();
2389 pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
2392 pa_pstream_send_tagstruct(c->pstream, reply);
2396 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2397 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2398 const char *name = NULL;
2400 pa_tagstruct *reply;
2402 pa_native_connection_assert_ref(c);
2405 p = pa_proplist_new();
2407 if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
2408 (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2409 !pa_tagstruct_eof(t)) {
2412 pa_proplist_free(p);
2417 if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
2418 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2419 pa_proplist_free(p);
2423 pa_client_update_proplist(c->client, PA_UPDATE_REPLACE, p);
2424 pa_proplist_free(p);
2426 reply = reply_new(tag);
2428 if (c->version >= 13)
2429 pa_tagstruct_putu32(reply, c->client->index);
2431 pa_pstream_send_tagstruct(c->pstream, reply);
2434 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2435 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2437 uint32_t idx = PA_IDXSET_INVALID;
2439 pa_native_connection_assert_ref(c);
2442 if (pa_tagstruct_gets(t, &name) < 0 ||
2443 !pa_tagstruct_eof(t)) {
2448 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2449 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2451 if (command == PA_COMMAND_LOOKUP_SINK) {
2453 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK)))
2457 pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
2458 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE)))
2459 idx = source->index;
2462 if (idx == PA_IDXSET_INVALID)
2463 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2465 pa_tagstruct *reply;
2466 reply = reply_new(tag);
2467 pa_tagstruct_putu32(reply, idx);
2468 pa_pstream_send_tagstruct(c->pstream, reply);
2472 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2473 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2477 pa_native_connection_assert_ref(c);
2480 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2481 !pa_tagstruct_eof(t)) {
2486 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2487 s = pa_idxset_get_by_index(c->output_streams, idx);
2488 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2489 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2491 pa_asyncmsgq_post(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_DRAIN, PA_UINT_TO_PTR(tag), 0, NULL, NULL);
2494 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2495 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2496 pa_tagstruct *reply;
2497 const pa_mempool_stat *stat;
2499 pa_native_connection_assert_ref(c);
2502 if (!pa_tagstruct_eof(t)) {
2507 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2509 stat = pa_mempool_get_stat(c->protocol->core->mempool);
2511 reply = reply_new(tag);
2512 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
2513 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
2514 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
2515 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
2516 pa_tagstruct_putu32(reply, (uint32_t) pa_scache_total_size(c->protocol->core));
2517 pa_pstream_send_tagstruct(c->pstream, reply);
2520 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2521 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2522 pa_tagstruct *reply;
2524 struct timeval tv, now;
2527 pa_native_connection_assert_ref(c);
2530 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2531 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2532 !pa_tagstruct_eof(t)) {
2537 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2538 s = pa_idxset_get_by_index(c->output_streams, idx);
2539 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2540 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2542 /* Get an atomic snapshot of all timing parameters */
2543 pa_assert_se(pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0);
2545 reply = reply_new(tag);
2546 pa_tagstruct_put_usec(reply,
2547 s->current_sink_latency +
2548 pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sample_spec));
2549 pa_tagstruct_put_usec(reply, 0);
2550 pa_tagstruct_put_boolean(reply,
2551 s->playing_for > 0 &&
2552 pa_sink_get_state(s->sink_input->sink) == PA_SINK_RUNNING &&
2553 pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
2554 pa_tagstruct_put_timeval(reply, &tv);
2555 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2556 pa_tagstruct_puts64(reply, s->write_index);
2557 pa_tagstruct_puts64(reply, s->read_index);
2559 if (c->version >= 13) {
2560 pa_tagstruct_putu64(reply, s->underrun_for);
2561 pa_tagstruct_putu64(reply, s->playing_for);
2564 pa_pstream_send_tagstruct(c->pstream, reply);
2567 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2568 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2569 pa_tagstruct *reply;
2571 struct timeval tv, now;
2574 pa_native_connection_assert_ref(c);
2577 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2578 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2579 !pa_tagstruct_eof(t)) {
2584 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2585 s = pa_idxset_get_by_index(c->record_streams, idx);
2586 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2588 /* Get an atomic snapshot of all timing parameters */
2589 pa_assert_se(pa_asyncmsgq_send(s->source_output->source->asyncmsgq, PA_MSGOBJECT(s->source_output), SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0);
2591 reply = reply_new(tag);
2592 pa_tagstruct_put_usec(reply, s->current_monitor_latency);
2593 pa_tagstruct_put_usec(reply,
2594 s->current_source_latency +
2595 pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->sample_spec));
2596 pa_tagstruct_put_boolean(reply,
2597 pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING &&
2598 pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING);
2599 pa_tagstruct_put_timeval(reply, &tv);
2600 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2601 pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
2602 pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
2603 pa_pstream_send_tagstruct(c->pstream, reply);
2606 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2607 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2610 const char *name = NULL;
2613 pa_tagstruct *reply;
2616 pa_native_connection_assert_ref(c);
2619 if (pa_tagstruct_gets(t, &name) < 0 ||
2620 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2621 pa_tagstruct_get_channel_map(t, &map) < 0 ||
2622 pa_tagstruct_getu32(t, &length) < 0) {
2627 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2628 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2629 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2630 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2631 CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
2632 CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
2634 p = pa_proplist_new();
2636 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2637 !pa_tagstruct_eof(t)) {
2640 pa_proplist_free(p);
2644 if (c->version < 13)
2645 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2647 if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID)))
2648 name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME);
2650 if (!name || !pa_namereg_is_valid_name(name)) {
2651 pa_proplist_free(p);
2652 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
2655 s = upload_stream_new(c, &ss, &map, name, length, p);
2656 pa_proplist_free(p);
2658 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
2660 reply = reply_new(tag);
2661 pa_tagstruct_putu32(reply, s->index);
2662 pa_tagstruct_putu32(reply, length);
2663 pa_pstream_send_tagstruct(c->pstream, reply);
2666 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2667 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2672 pa_native_connection_assert_ref(c);
2675 if (pa_tagstruct_getu32(t, &channel) < 0 ||
2676 !pa_tagstruct_eof(t)) {
2681 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2683 s = pa_idxset_get_by_index(c->output_streams, channel);
2684 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2685 CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2687 if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
2688 pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
2690 pa_pstream_send_simple_ack(c->pstream, tag);
2692 upload_stream_unlink(s);
2695 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2696 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2697 uint32_t sink_index;
2700 const char *name, *sink_name;
2703 pa_tagstruct *reply;
2705 pa_native_connection_assert_ref(c);
2708 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2710 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
2711 pa_tagstruct_gets(t, &sink_name) < 0 ||
2712 pa_tagstruct_getu32(t, &volume) < 0 ||
2713 pa_tagstruct_gets(t, &name) < 0) {
2718 CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name(sink_name), tag, PA_ERR_INVALID);
2719 CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
2720 CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2721 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2723 if (sink_index != PA_INVALID_INDEX)
2724 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
2726 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK);
2728 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
2730 p = pa_proplist_new();
2732 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2733 !pa_tagstruct_eof(t)) {
2735 pa_proplist_free(p);
2739 pa_proplist_update(p, PA_UPDATE_MERGE, c->client->proplist);
2741 if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
2742 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2743 pa_proplist_free(p);
2747 pa_proplist_free(p);
2749 reply = reply_new(tag);
2751 if (c->version >= 13)
2752 pa_tagstruct_putu32(reply, idx);
2754 pa_pstream_send_tagstruct(c->pstream, reply);
2757 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2758 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2761 pa_native_connection_assert_ref(c);
2764 if (pa_tagstruct_gets(t, &name) < 0 ||
2765 !pa_tagstruct_eof(t)) {
2770 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2771 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2773 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
2774 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2778 pa_pstream_send_simple_ack(c->pstream, tag);
2781 static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
2784 pa_assert(original);
2788 if (c->version < 12) {
2789 /* Before protocol version 12 we didn't support S32 samples,
2790 * so we need to lie about this to the client */
2792 if (fixed->format == PA_SAMPLE_S32LE)
2793 fixed->format = PA_SAMPLE_FLOAT32LE;
2794 if (fixed->format == PA_SAMPLE_S32BE)
2795 fixed->format = PA_SAMPLE_FLOAT32BE;
2798 if (c->version < 15) {
2799 if (fixed->format == PA_SAMPLE_S24LE || fixed->format == PA_SAMPLE_S24_32LE)
2800 fixed->format = PA_SAMPLE_FLOAT32LE;
2801 if (fixed->format == PA_SAMPLE_S24BE || fixed->format == PA_SAMPLE_S24_32BE)
2802 fixed->format = PA_SAMPLE_FLOAT32BE;
2806 static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) {
2807 pa_sample_spec fixed_ss;
2810 pa_sink_assert_ref(sink);
2812 fixup_sample_spec(c, &fixed_ss, &sink->sample_spec);
2816 PA_TAG_U32, sink->index,
2817 PA_TAG_STRING, sink->name,
2818 PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2819 PA_TAG_SAMPLE_SPEC, &fixed_ss,
2820 PA_TAG_CHANNEL_MAP, &sink->channel_map,
2821 PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
2822 PA_TAG_CVOLUME, pa_sink_get_volume(sink, FALSE, FALSE),
2823 PA_TAG_BOOLEAN, pa_sink_get_mute(sink, FALSE),
2824 PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
2825 PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
2826 PA_TAG_USEC, pa_sink_get_latency(sink),
2827 PA_TAG_STRING, sink->driver,
2828 PA_TAG_U32, sink->flags,
2831 if (c->version >= 13) {
2832 pa_tagstruct_put_proplist(t, sink->proplist);
2833 pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
2836 if (c->version >= 15) {
2837 pa_tagstruct_put_volume(t, sink->base_volume);
2838 if (PA_UNLIKELY(pa_sink_get_state(sink) == PA_SINK_INVALID_STATE))
2839 pa_log_error("Internal sink state is invalid.");
2840 pa_tagstruct_putu32(t, pa_sink_get_state(sink));
2841 pa_tagstruct_putu32(t, sink->n_volume_steps);
2842 pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX);
2846 static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
2847 pa_sample_spec fixed_ss;
2850 pa_source_assert_ref(source);
2852 fixup_sample_spec(c, &fixed_ss, &source->sample_spec);
2856 PA_TAG_U32, source->index,
2857 PA_TAG_STRING, source->name,
2858 PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2859 PA_TAG_SAMPLE_SPEC, &fixed_ss,
2860 PA_TAG_CHANNEL_MAP, &source->channel_map,
2861 PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
2862 PA_TAG_CVOLUME, pa_source_get_volume(source, FALSE),
2863 PA_TAG_BOOLEAN, pa_source_get_mute(source, FALSE),
2864 PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
2865 PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
2866 PA_TAG_USEC, pa_source_get_latency(source),
2867 PA_TAG_STRING, source->driver,
2868 PA_TAG_U32, source->flags,
2871 if (c->version >= 13) {
2872 pa_tagstruct_put_proplist(t, source->proplist);
2873 pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
2876 if (c->version >= 15) {
2877 pa_tagstruct_put_volume(t, source->base_volume);
2878 if (PA_UNLIKELY(pa_source_get_state(source) == PA_SOURCE_INVALID_STATE))
2879 pa_log_error("Internal source state is invalid.");
2880 pa_tagstruct_putu32(t, pa_source_get_state(source));
2881 pa_tagstruct_putu32(t, source->n_volume_steps);
2882 pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX);
2886 static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
2890 pa_tagstruct_putu32(t, client->index);
2891 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
2892 pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
2893 pa_tagstruct_puts(t, client->driver);
2895 if (c->version >= 13)
2896 pa_tagstruct_put_proplist(t, client->proplist);
2899 static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
2906 pa_tagstruct_putu32(t, card->index);
2907 pa_tagstruct_puts(t, card->name);
2908 pa_tagstruct_putu32(t, card->module ? card->module->index : PA_INVALID_INDEX);
2909 pa_tagstruct_puts(t, card->driver);
2911 pa_tagstruct_putu32(t, card->profiles ? pa_hashmap_size(card->profiles) : 0);
2913 if (card->profiles) {
2914 while ((p = pa_hashmap_iterate(card->profiles, &state, NULL))) {
2915 pa_tagstruct_puts(t, p->name);
2916 pa_tagstruct_puts(t, p->description);
2917 pa_tagstruct_putu32(t, p->n_sinks);
2918 pa_tagstruct_putu32(t, p->n_sources);
2919 pa_tagstruct_putu32(t, p->priority);
2923 pa_tagstruct_puts(t, card->active_profile ? card->active_profile->name : NULL);
2924 pa_tagstruct_put_proplist(t, card->proplist);
2927 static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module) {
2931 pa_tagstruct_putu32(t, module->index);
2932 pa_tagstruct_puts(t, module->name);
2933 pa_tagstruct_puts(t, module->argument);
2934 pa_tagstruct_putu32(t, (uint32_t) pa_module_get_n_used(module));
2936 if (c->version < 15)
2937 pa_tagstruct_put_boolean(t, FALSE); /* autoload is obsolete */
2939 if (c->version >= 15)
2940 pa_tagstruct_put_proplist(t, module->proplist);
2943 static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) {
2944 pa_sample_spec fixed_ss;
2945 pa_usec_t sink_latency;
2949 pa_sink_input_assert_ref(s);
2951 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
2953 pa_tagstruct_putu32(t, s->index);
2954 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
2955 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
2956 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
2957 pa_tagstruct_putu32(t, s->sink->index);
2958 pa_tagstruct_put_sample_spec(t, &fixed_ss);
2959 pa_tagstruct_put_channel_map(t, &s->channel_map);
2960 pa_tagstruct_put_cvolume(t, pa_sink_input_get_volume(s, &v, TRUE));
2961 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
2962 pa_tagstruct_put_usec(t, sink_latency);
2963 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
2964 pa_tagstruct_puts(t, s->driver);
2965 if (c->version >= 11)
2966 pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
2967 if (c->version >= 13)
2968 pa_tagstruct_put_proplist(t, s->proplist);
2971 static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
2972 pa_sample_spec fixed_ss;
2973 pa_usec_t source_latency;
2976 pa_source_output_assert_ref(s);
2978 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
2980 pa_tagstruct_putu32(t, s->index);
2981 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
2982 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
2983 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
2984 pa_tagstruct_putu32(t, s->source->index);
2985 pa_tagstruct_put_sample_spec(t, &fixed_ss);
2986 pa_tagstruct_put_channel_map(t, &s->channel_map);
2987 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s, &source_latency));
2988 pa_tagstruct_put_usec(t, source_latency);
2989 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
2990 pa_tagstruct_puts(t, s->driver);
2992 if (c->version >= 13)
2993 pa_tagstruct_put_proplist(t, s->proplist);
2996 static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {
2997 pa_sample_spec fixed_ss;
3003 if (e->memchunk.memblock)
3004 fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
3006 memset(&fixed_ss, 0, sizeof(fixed_ss));
3008 pa_tagstruct_putu32(t, e->index);
3009 pa_tagstruct_puts(t, e->name);
3011 if (e->volume_is_set)
3014 pa_cvolume_init(&v);
3016 pa_tagstruct_put_cvolume(t, &v);
3017 pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0);
3018 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3019 pa_tagstruct_put_channel_map(t, &e->channel_map);
3020 pa_tagstruct_putu32(t, (uint32_t) e->memchunk.length);
3021 pa_tagstruct_put_boolean(t, e->lazy);
3022 pa_tagstruct_puts(t, e->filename);
3024 if (c->version >= 13)
3025 pa_tagstruct_put_proplist(t, e->proplist);
3028 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3029 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3031 pa_sink *sink = NULL;
3032 pa_source *source = NULL;
3033 pa_client *client = NULL;
3034 pa_card *card = NULL;
3035 pa_module *module = NULL;
3036 pa_sink_input *si = NULL;
3037 pa_source_output *so = NULL;
3038 pa_scache_entry *sce = NULL;
3039 const char *name = NULL;
3040 pa_tagstruct *reply;
3042 pa_native_connection_assert_ref(c);
3045 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3046 (command != PA_COMMAND_GET_CLIENT_INFO &&
3047 command != PA_COMMAND_GET_MODULE_INFO &&
3048 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
3049 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
3050 pa_tagstruct_gets(t, &name) < 0) ||
3051 !pa_tagstruct_eof(t)) {
3056 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3057 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3058 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3059 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3060 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3062 if (command == PA_COMMAND_GET_SINK_INFO) {
3063 if (idx != PA_INVALID_INDEX)
3064 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3066 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3067 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
3068 if (idx != PA_INVALID_INDEX)
3069 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3071 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3072 } else if (command == PA_COMMAND_GET_CARD_INFO) {
3073 if (idx != PA_INVALID_INDEX)
3074 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
3076 card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
3077 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
3078 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3079 else if (command == PA_COMMAND_GET_MODULE_INFO)
3080 module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3081 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
3082 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3083 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
3084 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3086 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
3087 if (idx != PA_INVALID_INDEX)
3088 sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
3090 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
3093 if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
3094 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3098 reply = reply_new(tag);
3100 sink_fill_tagstruct(c, reply, sink);
3102 source_fill_tagstruct(c, reply, source);
3104 client_fill_tagstruct(c, reply, client);
3106 card_fill_tagstruct(c, reply, card);
3108 module_fill_tagstruct(c, reply, module);
3110 sink_input_fill_tagstruct(c, reply, si);
3112 source_output_fill_tagstruct(c, reply, so);
3114 scache_fill_tagstruct(c, reply, sce);
3115 pa_pstream_send_tagstruct(c->pstream, reply);
3118 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3119 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3123 pa_tagstruct *reply;
3125 pa_native_connection_assert_ref(c);
3128 if (!pa_tagstruct_eof(t)) {
3133 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3135 reply = reply_new(tag);
3137 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3138 i = c->protocol->core->sinks;
3139 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3140 i = c->protocol->core->sources;
3141 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3142 i = c->protocol->core->clients;
3143 else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3144 i = c->protocol->core->cards;
3145 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3146 i = c->protocol->core->modules;
3147 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3148 i = c->protocol->core->sink_inputs;
3149 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3150 i = c->protocol->core->source_outputs;
3152 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3153 i = c->protocol->core->scache;
3157 for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
3158 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3159 sink_fill_tagstruct(c, reply, p);
3160 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3161 source_fill_tagstruct(c, reply, p);
3162 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3163 client_fill_tagstruct(c, reply, p);
3164 else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3165 card_fill_tagstruct(c, reply, p);
3166 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3167 module_fill_tagstruct(c, reply, p);
3168 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3169 sink_input_fill_tagstruct(c, reply, p);
3170 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3171 source_output_fill_tagstruct(c, reply, p);
3173 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3174 scache_fill_tagstruct(c, reply, p);
3179 pa_pstream_send_tagstruct(c->pstream, reply);
3182 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3183 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3184 pa_tagstruct *reply;
3187 pa_source *def_source;
3188 pa_sample_spec fixed_ss;
3190 pa_native_connection_assert_ref(c);
3193 if (!pa_tagstruct_eof(t)) {
3198 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3200 reply = reply_new(tag);
3201 pa_tagstruct_puts(reply, PACKAGE_NAME);
3202 pa_tagstruct_puts(reply, PACKAGE_VERSION);
3203 pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt)));
3204 pa_tagstruct_puts(reply, pa_get_host_name(txt, sizeof(txt)));
3206 fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
3207 pa_tagstruct_put_sample_spec(reply, &fixed_ss);
3209 def_sink = pa_namereg_get_default_sink(c->protocol->core);
3210 pa_tagstruct_puts(reply, def_sink ? def_sink->name : NULL);
3211 def_source = pa_namereg_get_default_source(c->protocol->core);
3212 pa_tagstruct_puts(reply, def_source ? def_source->name : NULL);
3214 pa_tagstruct_putu32(reply, c->protocol->core->cookie);
3216 if (c->version >= 15)
3217 pa_tagstruct_put_channel_map(reply, &c->protocol->core->default_channel_map);
3219 pa_pstream_send_tagstruct(c->pstream, reply);
3222 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
3224 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3226 pa_native_connection_assert_ref(c);
3228 t = pa_tagstruct_new(NULL, 0);
3229 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
3230 pa_tagstruct_putu32(t, (uint32_t) -1);
3231 pa_tagstruct_putu32(t, e);
3232 pa_tagstruct_putu32(t, idx);
3233 pa_pstream_send_tagstruct(c->pstream, t);
3236 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3237 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3238 pa_subscription_mask_t m;
3240 pa_native_connection_assert_ref(c);
3243 if (pa_tagstruct_getu32(t, &m) < 0 ||
3244 !pa_tagstruct_eof(t)) {
3249 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3250 CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
3252 if (c->subscription)
3253 pa_subscription_free(c->subscription);
3256 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
3257 pa_assert(c->subscription);
3259 c->subscription = NULL;
3261 pa_pstream_send_simple_ack(c->pstream, tag);
3264 static void command_set_volume(
3271 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3274 pa_sink *sink = NULL;
3275 pa_source *source = NULL;
3276 pa_sink_input *si = NULL;
3277 const char *name = NULL;
3279 pa_native_connection_assert_ref(c);
3282 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3283 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3284 (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3285 pa_tagstruct_get_cvolume(t, &volume) ||
3286 !pa_tagstruct_eof(t)) {
3291 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3292 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3293 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3294 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3295 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3296 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
3300 case PA_COMMAND_SET_SINK_VOLUME:
3301 if (idx != PA_INVALID_INDEX)
3302 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3304 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3307 case PA_COMMAND_SET_SOURCE_VOLUME:
3308 if (idx != PA_INVALID_INDEX)
3309 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3311 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3314 case PA_COMMAND_SET_SINK_INPUT_VOLUME:
3315 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3319 pa_assert_not_reached();
3322 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3325 pa_sink_set_volume(sink, &volume, TRUE, TRUE, TRUE);
3327 pa_source_set_volume(source, &volume);
3329 pa_sink_input_set_volume(si, &volume, TRUE, TRUE);
3331 pa_pstream_send_simple_ack(c->pstream, tag);
3334 static void command_set_mute(
3341 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3344 pa_sink *sink = NULL;
3345 pa_source *source = NULL;
3346 pa_sink_input *si = NULL;
3347 const char *name = NULL;
3349 pa_native_connection_assert_ref(c);
3352 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3353 (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3354 (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3355 pa_tagstruct_get_boolean(t, &mute) ||
3356 !pa_tagstruct_eof(t)) {
3361 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3362 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3363 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3364 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3365 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3369 case PA_COMMAND_SET_SINK_MUTE:
3371 if (idx != PA_INVALID_INDEX)
3372 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3374 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3378 case PA_COMMAND_SET_SOURCE_MUTE:
3379 if (idx != PA_INVALID_INDEX)
3380 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3382 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3386 case PA_COMMAND_SET_SINK_INPUT_MUTE:
3387 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3391 pa_assert_not_reached();
3394 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3397 pa_sink_set_mute(sink, mute);
3399 pa_source_set_mute(source, mute);
3401 pa_sink_input_set_mute(si, mute, TRUE);
3403 pa_pstream_send_simple_ack(c->pstream, tag);
3406 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3407 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3412 pa_native_connection_assert_ref(c);
3415 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3416 pa_tagstruct_get_boolean(t, &b) < 0 ||
3417 !pa_tagstruct_eof(t)) {
3422 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3423 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3424 s = pa_idxset_get_by_index(c->output_streams, idx);
3425 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3426 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3428 pa_sink_input_cork(s->sink_input, b);
3431 s->is_underrun = TRUE;
3433 pa_pstream_send_simple_ack(c->pstream, tag);
3436 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3437 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3441 pa_native_connection_assert_ref(c);
3444 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3445 !pa_tagstruct_eof(t)) {
3450 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3451 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3452 s = pa_idxset_get_by_index(c->output_streams, idx);
3453 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3454 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3457 case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
3458 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
3461 case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
3462 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
3465 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
3466 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
3470 pa_assert_not_reached();
3473 pa_pstream_send_simple_ack(c->pstream, tag);
3476 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3477 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3482 pa_native_connection_assert_ref(c);
3485 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3486 pa_tagstruct_get_boolean(t, &b) < 0 ||
3487 !pa_tagstruct_eof(t)) {
3492 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3493 s = pa_idxset_get_by_index(c->record_streams, idx);
3494 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3496 pa_source_output_cork(s->source_output, b);
3497 pa_memblockq_prebuf_force(s->memblockq);
3498 pa_pstream_send_simple_ack(c->pstream, tag);
3501 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3502 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3506 pa_native_connection_assert_ref(c);
3509 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3510 !pa_tagstruct_eof(t)) {
3515 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3516 s = pa_idxset_get_by_index(c->record_streams, idx);
3517 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3519 pa_memblockq_flush_read(s->memblockq);
3520 pa_pstream_send_simple_ack(c->pstream, tag);
3523 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3524 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3527 pa_tagstruct *reply;
3529 pa_native_connection_assert_ref(c);
3532 memset(&a, 0, sizeof(a));
3534 if (pa_tagstruct_getu32(t, &idx) < 0) {
3539 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3541 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
3543 pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3545 s = pa_idxset_get_by_index(c->output_streams, idx);
3546 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3547 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3549 if (pa_tagstruct_get(
3551 PA_TAG_U32, &a.maxlength,
3552 PA_TAG_U32, &a.tlength,
3553 PA_TAG_U32, &a.prebuf,
3554 PA_TAG_U32, &a.minreq,
3555 PA_TAG_INVALID) < 0 ||
3556 (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3557 (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3558 !pa_tagstruct_eof(t)) {
3563 s->adjust_latency = adjust_latency;
3564 s->early_requests = early_requests;
3567 fix_playback_buffer_attr(s);
3568 pa_assert_se(pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR, NULL, 0, NULL) == 0);
3570 reply = reply_new(tag);
3571 pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3572 pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
3573 pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
3574 pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
3576 if (c->version >= 13)
3577 pa_tagstruct_put_usec(reply, s->configured_sink_latency);
3581 pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3582 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
3584 s = pa_idxset_get_by_index(c->record_streams, idx);
3585 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3587 if (pa_tagstruct_get(
3589 PA_TAG_U32, &a.maxlength,
3590 PA_TAG_U32, &a.fragsize,
3591 PA_TAG_INVALID) < 0 ||
3592 (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3593 (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3594 !pa_tagstruct_eof(t)) {
3599 s->adjust_latency = adjust_latency;
3600 s->early_requests = early_requests;
3603 fix_record_buffer_attr_pre(s);
3604 pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
3605 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
3606 fix_record_buffer_attr_post(s);
3608 reply = reply_new(tag);
3609 pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3610 pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
3612 if (c->version >= 13)
3613 pa_tagstruct_put_usec(reply, s->configured_source_latency);
3616 pa_pstream_send_tagstruct(c->pstream, reply);
3619 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3620 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3624 pa_native_connection_assert_ref(c);
3627 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3628 pa_tagstruct_getu32(t, &rate) < 0 ||
3629 !pa_tagstruct_eof(t)) {
3634 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3635 CHECK_VALIDITY(c->pstream, rate > 0 && rate <= PA_RATE_MAX, tag, PA_ERR_INVALID);
3637 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
3640 s = pa_idxset_get_by_index(c->output_streams, idx);
3641 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3642 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3644 pa_sink_input_set_rate(s->sink_input, rate);
3648 pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
3650 s = pa_idxset_get_by_index(c->record_streams, idx);
3651 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3653 pa_source_output_set_rate(s->source_output, rate);
3656 pa_pstream_send_simple_ack(c->pstream, tag);
3659 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3660 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3665 pa_native_connection_assert_ref(c);
3668 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3670 p = pa_proplist_new();
3672 if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
3674 if (pa_tagstruct_getu32(t, &mode) < 0 ||
3675 pa_tagstruct_get_proplist(t, p) < 0 ||
3676 !pa_tagstruct_eof(t)) {
3678 pa_proplist_free(p);
3684 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3685 pa_tagstruct_getu32(t, &mode) < 0 ||
3686 pa_tagstruct_get_proplist(t, p) < 0 ||
3687 !pa_tagstruct_eof(t)) {
3689 pa_proplist_free(p);
3694 if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) {
3695 pa_proplist_free(p);
3696 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
3699 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
3702 s = pa_idxset_get_by_index(c->output_streams, idx);
3703 if (!s || !playback_stream_isinstance(s)) {
3704 pa_proplist_free(p);
3705 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3707 pa_sink_input_update_proplist(s->sink_input, mode, p);
3709 } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
3712 if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
3713 pa_proplist_free(p);
3714 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3716 pa_source_output_update_proplist(s->source_output, mode, p);
3719 pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
3721 pa_client_update_proplist(c->client, mode, p);
3724 pa_pstream_send_simple_ack(c->pstream, tag);
3725 pa_proplist_free(p);
3728 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3729 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3731 unsigned changed = 0;
3733 pa_strlist *l = NULL;
3735 pa_native_connection_assert_ref(c);
3738 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3740 if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
3742 if (pa_tagstruct_getu32(t, &idx) < 0) {
3748 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3751 s = pa_idxset_get_by_index(c->output_streams, idx);
3752 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3753 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3755 p = s->sink_input->proplist;
3757 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3760 s = pa_idxset_get_by_index(c->record_streams, idx);
3761 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3763 p = s->source_output->proplist;
3765 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3767 p = c->client->proplist;
3773 if (pa_tagstruct_gets(t, &k) < 0) {
3782 l = pa_strlist_prepend(l, k);
3785 if (!pa_tagstruct_eof(t)) {
3794 l = pa_strlist_pop(l, &z);
3799 changed += (unsigned) (pa_proplist_unset(p, z) >= 0);
3803 pa_pstream_send_simple_ack(c->pstream, tag);
3806 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3809 s = pa_idxset_get_by_index(c->output_streams, idx);
3810 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
3812 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3815 s = pa_idxset_get_by_index(c->record_streams, idx);
3816 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
3819 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3820 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
3825 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3826 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3829 pa_native_connection_assert_ref(c);
3832 if (pa_tagstruct_gets(t, &s) < 0 ||
3833 !pa_tagstruct_eof(t)) {
3838 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3839 CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID);
3841 if (command == PA_COMMAND_SET_DEFAULT_SOURCE) {
3844 source = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SOURCE);
3845 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
3847 pa_namereg_set_default_source(c->protocol->core, source);
3850 pa_assert(command == PA_COMMAND_SET_DEFAULT_SINK);
3852 sink = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SINK);
3853 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
3855 pa_namereg_set_default_sink(c->protocol->core, sink);
3858 pa_pstream_send_simple_ack(c->pstream, tag);
3861 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3862 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3866 pa_native_connection_assert_ref(c);
3869 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3870 pa_tagstruct_gets(t, &name) < 0 ||
3871 !pa_tagstruct_eof(t)) {
3876 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3877 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
3879 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
3882 s = pa_idxset_get_by_index(c->output_streams, idx);
3883 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3884 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3886 pa_sink_input_set_name(s->sink_input, name);
3890 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
3892 s = pa_idxset_get_by_index(c->record_streams, idx);
3893 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3895 pa_source_output_set_name(s->source_output, name);
3898 pa_pstream_send_simple_ack(c->pstream, tag);
3901 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3902 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3905 pa_native_connection_assert_ref(c);
3908 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3909 !pa_tagstruct_eof(t)) {
3914 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3916 if (command == PA_COMMAND_KILL_CLIENT) {
3919 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3920 CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
3922 pa_native_connection_ref(c);
3923 pa_client_kill(client);
3925 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
3928 s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3929 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3931 pa_native_connection_ref(c);
3932 pa_sink_input_kill(s);
3934 pa_source_output *s;
3936 pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
3938 s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3939 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3941 pa_native_connection_ref(c);
3942 pa_source_output_kill(s);
3945 pa_pstream_send_simple_ack(c->pstream, tag);
3946 pa_native_connection_unref(c);
3949 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3950 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3952 const char *name, *argument;
3953 pa_tagstruct *reply;
3955 pa_native_connection_assert_ref(c);
3958 if (pa_tagstruct_gets(t, &name) < 0 ||
3959 pa_tagstruct_gets(t, &argument) < 0 ||
3960 !pa_tagstruct_eof(t)) {
3965 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3966 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
3967 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
3969 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
3970 pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
3974 reply = reply_new(tag);
3975 pa_tagstruct_putu32(reply, m->index);
3976 pa_pstream_send_tagstruct(c->pstream, reply);
3979 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3980 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3984 pa_native_connection_assert_ref(c);
3987 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3988 !pa_tagstruct_eof(t)) {
3993 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3994 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3995 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
3997 pa_module_unload_request(m, FALSE);
3998 pa_pstream_send_simple_ack(c->pstream, tag);
4001 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4002 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4003 uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
4004 const char *name_device = NULL;
4006 pa_native_connection_assert_ref(c);
4009 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4010 pa_tagstruct_getu32(t, &idx_device) < 0 ||
4011 pa_tagstruct_gets(t, &name_device) < 0 ||
4012 !pa_tagstruct_eof(t)) {
4017 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4018 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4020 CHECK_VALIDITY(c->pstream, !name_device || pa_namereg_is_valid_name(name_device), tag, PA_ERR_INVALID);
4021 CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || name_device, tag, PA_ERR_INVALID);
4022 CHECK_VALIDITY(c->pstream, idx_device == PA_INVALID_INDEX || !name_device, tag, PA_ERR_INVALID);
4023 CHECK_VALIDITY(c->pstream, !name_device || idx_device == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4025 if (command == PA_COMMAND_MOVE_SINK_INPUT) {
4026 pa_sink_input *si = NULL;
4027 pa_sink *sink = NULL;
4029 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4031 if (idx_device != PA_INVALID_INDEX)
4032 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
4034 sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK);
4036 CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
4038 if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
4039 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4043 pa_source_output *so = NULL;
4046 pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
4048 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4050 if (idx_device != PA_INVALID_INDEX)
4051 source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
4053 source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE);
4055 CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
4057 if (pa_source_output_move_to(so, source, TRUE) < 0) {
4058 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4063 pa_pstream_send_simple_ack(c->pstream, tag);
4066 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4067 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4068 uint32_t idx = PA_INVALID_INDEX;
4069 const char *name = NULL;
4072 pa_native_connection_assert_ref(c);
4075 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4076 pa_tagstruct_gets(t, &name) < 0 ||
4077 pa_tagstruct_get_boolean(t, &b) < 0 ||
4078 !pa_tagstruct_eof(t)) {
4083 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4084 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name) || *name == 0, tag, PA_ERR_INVALID);
4085 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4086 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4087 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4089 if (command == PA_COMMAND_SUSPEND_SINK) {
4091 if (idx == PA_INVALID_INDEX && name && !*name) {
4093 pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
4095 if (pa_sink_suspend_all(c->protocol->core, b) < 0) {
4096 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4100 pa_sink *sink = NULL;
4102 if (idx != PA_INVALID_INDEX)
4103 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4105 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4107 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4109 if (pa_sink_suspend(sink, b) < 0) {
4110 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4116 pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
4118 if (idx == PA_INVALID_INDEX && name && !*name) {
4120 pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
4122 if (pa_source_suspend_all(c->protocol->core, b) < 0) {
4123 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4130 if (idx != PA_INVALID_INDEX)
4131 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4133 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4135 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4137 if (pa_source_suspend(source, b) < 0) {
4138 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4144 pa_pstream_send_simple_ack(c->pstream, tag);
4147 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4148 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4149 uint32_t idx = PA_INVALID_INDEX;
4150 const char *name = NULL;
4152 pa_native_protocol_ext_cb_t cb;
4154 pa_native_connection_assert_ref(c);
4157 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4158 pa_tagstruct_gets(t, &name) < 0) {
4163 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4164 CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
4165 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4166 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4167 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4169 if (idx != PA_INVALID_INDEX)
4170 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4172 for (m = pa_idxset_first(c->protocol->core->modules, &idx); m; m = pa_idxset_next(c->protocol->core->modules, &idx))
4173 if (strcmp(name, m->name) == 0)
4177 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
4178 CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4180 cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m);
4181 CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION);
4183 if (cb(c->protocol, m, c, tag, t) < 0)
4187 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4188 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4189 uint32_t idx = PA_INVALID_INDEX;
4190 const char *name = NULL, *profile = NULL;
4191 pa_card *card = NULL;
4193 pa_native_connection_assert_ref(c);
4196 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4197 pa_tagstruct_gets(t, &name) < 0 ||
4198 pa_tagstruct_gets(t, &profile) < 0 ||
4199 !pa_tagstruct_eof(t)) {
4204 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4205 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4206 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4207 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4208 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4210 if (idx != PA_INVALID_INDEX)
4211 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4213 card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
4215 CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4217 if (pa_card_set_profile(card, profile, TRUE) < 0) {
4218 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4222 pa_pstream_send_simple_ack(c->pstream, tag);
4225 /*** pstream callbacks ***/
4227 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
4228 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4232 pa_native_connection_assert_ref(c);
4234 if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
4235 pa_log("invalid packet.");
4236 native_connection_unlink(c);
4240 static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) {
4241 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4242 output_stream *stream;
4246 pa_native_connection_assert_ref(c);
4248 if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
4249 pa_log_debug("Client sent block for invalid stream.");
4254 /* pa_log("got %lu bytes", (unsigned long) chunk->length); */
4256 if (playback_stream_isinstance(stream)) {
4257 playback_stream *ps = PLAYBACK_STREAM(stream);
4259 if (chunk->memblock) {
4260 if (seek != PA_SEEK_RELATIVE || offset != 0)
4261 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL);
4263 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
4265 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset+chunk->length, NULL, NULL);
4268 upload_stream *u = UPLOAD_STREAM(stream);
4271 if (!u->memchunk.memblock) {
4272 if (u->length == chunk->length && chunk->memblock) {
4273 u->memchunk = *chunk;
4274 pa_memblock_ref(u->memchunk.memblock);
4277 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
4278 u->memchunk.index = u->memchunk.length = 0;
4282 pa_assert(u->memchunk.memblock);
4285 if (l > chunk->length)
4290 dst = pa_memblock_acquire(u->memchunk.memblock);
4292 if (chunk->memblock) {
4294 src = pa_memblock_acquire(chunk->memblock);
4296 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
4297 (uint8_t*) src + chunk->index, l);
4299 pa_memblock_release(chunk->memblock);
4301 pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec);
4303 pa_memblock_release(u->memchunk.memblock);
4305 u->memchunk.length += l;
4311 static void pstream_die_callback(pa_pstream *p, void *userdata) {
4312 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4315 pa_native_connection_assert_ref(c);
4317 native_connection_unlink(c);
4318 pa_log_info("Connection died.");
4321 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
4322 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4325 pa_native_connection_assert_ref(c);
4327 native_connection_send_memblock(c);
4330 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4333 if (!(q = pa_thread_mq_get()))
4334 pa_pstream_send_revoke(p, block_id);
4336 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4339 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4342 if (!(q = pa_thread_mq_get()))
4343 pa_pstream_send_release(p, block_id);
4345 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4348 /*** client callbacks ***/
4350 static void client_kill_cb(pa_client *c) {
4353 native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
4354 pa_log_info("Connection killed.");
4357 static void client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl) {
4359 pa_native_connection *c;
4362 c = PA_NATIVE_CONNECTION(client->userdata);
4363 pa_native_connection_assert_ref(c);
4365 if (c->version < 15)
4368 t = pa_tagstruct_new(NULL, 0);
4369 pa_tagstruct_putu32(t, PA_COMMAND_CLIENT_EVENT);
4370 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
4371 pa_tagstruct_puts(t, event);
4372 pa_tagstruct_put_proplist(t, pl);
4373 pa_pstream_send_tagstruct(c->pstream, t);
4376 /*** module entry points ***/
4378 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
4379 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4383 pa_native_connection_assert_ref(c);
4384 pa_assert(c->auth_timeout_event == e);
4386 if (!c->authorized) {
4387 native_connection_unlink(c);
4388 pa_log_info("Connection terminated due to authentication timeout.");
4392 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
4393 pa_native_connection *c;
4396 pa_client_new_data data;
4402 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
4403 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
4404 pa_iochannel_free(io);
4408 pa_client_new_data_init(&data);
4409 data.module = o->module;
4410 data.driver = __FILE__;
4411 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
4412 pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname);
4413 pa_proplist_sets(data.proplist, "native-protocol.peer", pname);
4414 client = pa_client_new(p->core, &data);
4415 pa_client_new_data_done(&data);
4420 c = pa_msgobject_new(pa_native_connection);
4421 c->parent.parent.free = native_connection_free;
4422 c->parent.process_msg = native_connection_process_msg;
4424 c->options = pa_native_options_ref(o);
4425 c->authorized = FALSE;
4427 if (o->auth_anonymous) {
4428 pa_log_info("Client authenticated anonymously.");
4429 c->authorized = TRUE;
4432 if (!c->authorized &&
4434 pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
4436 pa_log_info("Client authenticated by IP ACL.");
4437 c->authorized = TRUE;
4440 if (!c->authorized) {
4442 pa_gettimeofday(&tv);
4443 tv.tv_sec += AUTH_TIMEOUT;
4444 c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
4446 c->auth_timeout_event = NULL;
4448 c->is_local = pa_iochannel_socket_is_local(io);
4452 c->client->kill = client_kill_cb;
4453 c->client->send_event = client_send_event_cb;
4454 c->client->userdata = c;
4456 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
4457 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
4458 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
4459 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
4460 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
4461 pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
4462 pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
4464 c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
4466 c->record_streams = pa_idxset_new(NULL, NULL);
4467 c->output_streams = pa_idxset_new(NULL, NULL);
4469 c->rrobin_index = PA_IDXSET_INVALID;
4470 c->subscription = NULL;
4472 pa_idxset_put(p->connections, c, NULL);
4475 if (pa_iochannel_creds_supported(io))
4476 pa_iochannel_creds_enable(io);
4479 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
4482 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
4483 pa_native_connection *c;
4489 while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
4490 if (c->options->module == m)
4491 native_connection_unlink(c);
4494 static pa_native_protocol* native_protocol_new(pa_core *c) {
4495 pa_native_protocol *p;
4500 p = pa_xnew(pa_native_protocol, 1);
4503 p->connections = pa_idxset_new(NULL, NULL);
4507 p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
4509 for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4510 pa_hook_init(&p->hooks[h], p);
4512 pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
4517 pa_native_protocol* pa_native_protocol_get(pa_core *c) {
4518 pa_native_protocol *p;
4520 if ((p = pa_shared_get(c, "native-protocol")))
4521 return pa_native_protocol_ref(p);
4523 return native_protocol_new(c);
4526 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
4528 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4535 void pa_native_protocol_unref(pa_native_protocol *p) {
4536 pa_native_connection *c;
4540 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4542 if (PA_REFCNT_DEC(p) > 0)
4545 while ((c = pa_idxset_first(p->connections, NULL)))
4546 native_connection_unlink(c);
4548 pa_idxset_free(p->connections, NULL, NULL);
4550 pa_strlist_free(p->servers);
4552 for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4553 pa_hook_done(&p->hooks[h]);
4555 pa_hashmap_free(p->extensions, NULL, NULL);
4557 pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
4562 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name) {
4564 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4567 p->servers = pa_strlist_prepend(p->servers, name);
4569 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4572 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
4574 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4577 p->servers = pa_strlist_remove(p->servers, name);
4579 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4582 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
4584 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4589 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
4591 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4596 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb) {
4598 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4601 pa_assert(!pa_hashmap_get(p->extensions, m));
4603 pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) (unsigned long) cb) == 0);
4607 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
4609 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4612 pa_assert_se(pa_hashmap_remove(p->extensions, m));
4615 pa_native_options* pa_native_options_new(void) {
4616 pa_native_options *o;
4618 o = pa_xnew0(pa_native_options, 1);
4624 pa_native_options* pa_native_options_ref(pa_native_options *o) {
4626 pa_assert(PA_REFCNT_VALUE(o) >= 1);
4633 void pa_native_options_unref(pa_native_options *o) {
4635 pa_assert(PA_REFCNT_VALUE(o) >= 1);
4637 if (PA_REFCNT_DEC(o) > 0)
4640 pa_xfree(o->auth_group);
4643 pa_ip_acl_free(o->auth_ip_acl);
4646 pa_auth_cookie_unref(o->auth_cookie);
4651 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
4656 pa_assert(PA_REFCNT_VALUE(o) >= 1);
4659 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
4660 pa_log("auth-anonymous= expects a boolean argument.");
4665 if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &enabled) < 0) {
4666 pa_log("auth-group-enabled= expects a boolean argument.");
4670 pa_xfree(o->auth_group);
4671 o->auth_group = enabled ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
4675 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4678 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
4681 if (!(ipa = pa_ip_acl_new(acl))) {
4682 pa_log("Failed to parse IP ACL '%s'", acl);
4687 pa_ip_acl_free(o->auth_ip_acl);
4689 o->auth_ip_acl = ipa;
4693 if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
4694 pa_log("auth-cookie-enabled= expects a boolean argument.");
4699 pa_auth_cookie_unref(o->auth_cookie);
4704 /* The new name for this is 'auth-cookie', for compat reasons
4705 * we check the old name too */
4706 if (!(cn = pa_modargs_get_value(ma, "auth-cookie", NULL)))
4707 if (!(cn = pa_modargs_get_value(ma, "cookie", NULL)))
4708 cn = PA_NATIVE_COOKIE_FILE;
4710 if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, PA_NATIVE_COOKIE_LENGTH)))
4714 o->auth_cookie = NULL;
4719 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
4720 pa_native_connection_assert_ref(c);