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/rtclock.h>
33 #include <pulse/timeval.h>
34 #include <pulse/version.h>
35 #include <pulse/utf8.h>
36 #include <pulse/util.h>
37 #include <pulse/xmalloc.h>
39 #include <pulsecore/native-common.h>
40 #include <pulsecore/packet.h>
41 #include <pulsecore/client.h>
42 #include <pulsecore/source-output.h>
43 #include <pulsecore/sink-input.h>
44 #include <pulsecore/pstream.h>
45 #include <pulsecore/tagstruct.h>
46 #include <pulsecore/pdispatch.h>
47 #include <pulsecore/pstream-util.h>
48 #include <pulsecore/authkey.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/core-scache.h>
51 #include <pulsecore/core-subscribe.h>
52 #include <pulsecore/log.h>
53 #include <pulsecore/strlist.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/sample-util.h>
56 #include <pulsecore/llist.h>
57 #include <pulsecore/creds.h>
58 #include <pulsecore/core-util.h>
59 #include <pulsecore/ipacl.h>
60 #include <pulsecore/thread-mq.h>
62 #include "protocol-native.h"
64 /* Kick a client if it doesn't authenticate within this time */
65 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
67 /* Don't accept more connection than this */
68 #define MAX_CONNECTIONS 64
70 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
71 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
72 #define DEFAULT_PROCESS_MSEC 20 /* 20ms */
73 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
75 struct pa_native_protocol;
77 typedef struct record_stream {
80 pa_native_connection *connection;
83 pa_source_output *source_output;
84 pa_memblockq *memblockq;
86 pa_bool_t adjust_latency:1;
87 pa_bool_t early_requests:1;
89 pa_buffer_attr buffer_attr;
91 pa_atomic_t on_the_fly;
92 pa_usec_t configured_source_latency;
95 /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
96 size_t on_the_fly_snapshot;
97 pa_usec_t current_monitor_latency;
98 pa_usec_t current_source_latency;
101 #define RECORD_STREAM(o) (record_stream_cast(o))
102 PA_DEFINE_PRIVATE_CLASS(record_stream, pa_msgobject);
104 typedef struct output_stream {
108 #define OUTPUT_STREAM(o) (output_stream_cast(o))
109 PA_DEFINE_PRIVATE_CLASS(output_stream, pa_msgobject);
111 typedef struct playback_stream {
112 output_stream parent;
114 pa_native_connection *connection;
117 pa_sink_input *sink_input;
118 pa_memblockq *memblockq;
120 pa_bool_t adjust_latency:1;
121 pa_bool_t early_requests:1;
123 pa_bool_t is_underrun:1;
124 pa_bool_t drain_request:1;
128 /* Optimization to avoid too many rewinds with a lot of small blocks */
129 pa_atomic_t seek_or_post_in_queue;
133 pa_usec_t configured_sink_latency;
134 pa_buffer_attr buffer_attr;
136 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
137 int64_t read_index, write_index;
138 size_t render_memblockq_length;
139 pa_usec_t current_sink_latency;
140 uint64_t playing_for, underrun_for;
143 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
144 PA_DEFINE_PRIVATE_CLASS(playback_stream, output_stream);
146 typedef struct upload_stream {
147 output_stream parent;
149 pa_native_connection *connection;
152 pa_memchunk memchunk;
155 pa_sample_spec sample_spec;
156 pa_channel_map channel_map;
157 pa_proplist *proplist;
160 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
161 PA_DEFINE_PRIVATE_CLASS(upload_stream, output_stream);
163 struct pa_native_connection {
165 pa_native_protocol *protocol;
166 pa_native_options *options;
167 pa_bool_t authorized:1;
168 pa_bool_t is_local:1;
172 pa_pdispatch *pdispatch;
173 pa_idxset *record_streams, *output_streams;
174 uint32_t rrobin_index;
175 pa_subscription *subscription;
176 pa_time_event *auth_timeout_event;
179 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
180 PA_DEFINE_PRIVATE_CLASS(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);
287 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
289 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
290 [PA_COMMAND_ERROR] = NULL,
291 [PA_COMMAND_TIMEOUT] = NULL,
292 [PA_COMMAND_REPLY] = NULL,
293 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
294 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
295 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
296 [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
297 [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
298 [PA_COMMAND_AUTH] = command_auth,
299 [PA_COMMAND_REQUEST] = NULL,
300 [PA_COMMAND_EXIT] = command_exit,
301 [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
302 [PA_COMMAND_LOOKUP_SINK] = command_lookup,
303 [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
304 [PA_COMMAND_STAT] = command_stat,
305 [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
306 [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
307 [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
308 [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
309 [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
310 [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
311 [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
312 [PA_COMMAND_GET_SINK_INFO] = command_get_info,
313 [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
314 [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
315 [PA_COMMAND_GET_CARD_INFO] = command_get_info,
316 [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
317 [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
318 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
319 [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
320 [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
321 [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
322 [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
323 [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
324 [PA_COMMAND_GET_CARD_INFO_LIST] = command_get_info_list,
325 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
326 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
327 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
328 [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
329 [PA_COMMAND_SUBSCRIBE] = command_subscribe,
331 [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
332 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
333 [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
335 [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
336 [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
337 [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
339 [PA_COMMAND_SUSPEND_SINK] = command_suspend,
340 [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
342 [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
343 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
344 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
345 [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
347 [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
348 [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
350 [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
351 [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
352 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
353 [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
354 [PA_COMMAND_KILL_CLIENT] = command_kill,
355 [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
356 [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
357 [PA_COMMAND_LOAD_MODULE] = command_load_module,
358 [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
360 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE] = NULL,
361 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE] = NULL,
362 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE] = NULL,
363 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE] = NULL,
365 [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
366 [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream,
368 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
369 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
371 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
372 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
374 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = command_update_proplist,
375 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = command_update_proplist,
376 [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = command_update_proplist,
378 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = command_remove_proplist,
379 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
380 [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
382 [PA_COMMAND_SET_CARD_PROFILE] = command_set_card_profile,
384 [PA_COMMAND_SET_SINK_PORT] = command_set_sink_or_source_port,
385 [PA_COMMAND_SET_SOURCE_PORT] = command_set_sink_or_source_port,
387 [PA_COMMAND_EXTENSION] = command_extension
390 /* structure management */
392 /* Called from main context */
393 static void upload_stream_unlink(upload_stream *s) {
399 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
400 s->connection = NULL;
401 upload_stream_unref(s);
404 /* Called from main context */
405 static void upload_stream_free(pa_object *o) {
406 upload_stream *s = UPLOAD_STREAM(o);
409 upload_stream_unlink(s);
414 pa_proplist_free(s->proplist);
416 if (s->memchunk.memblock)
417 pa_memblock_unref(s->memchunk.memblock);
422 /* Called from main context */
423 static upload_stream* upload_stream_new(
424 pa_native_connection *c,
425 const pa_sample_spec *ss,
426 const pa_channel_map *map,
436 pa_assert(length > 0);
439 s = pa_msgobject_new(upload_stream);
440 s->parent.parent.parent.free = upload_stream_free;
442 s->sample_spec = *ss;
443 s->channel_map = *map;
444 s->name = pa_xstrdup(name);
445 pa_memchunk_reset(&s->memchunk);
447 s->proplist = pa_proplist_copy(p);
448 pa_proplist_update(s->proplist, PA_UPDATE_MERGE, c->client->proplist);
450 pa_idxset_put(c->output_streams, s, &s->index);
455 /* Called from main context */
456 static void record_stream_unlink(record_stream *s) {
462 if (s->source_output) {
463 pa_source_output_unlink(s->source_output);
464 pa_source_output_unref(s->source_output);
465 s->source_output = NULL;
468 pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
469 s->connection = NULL;
470 record_stream_unref(s);
473 /* Called from main context */
474 static void record_stream_free(pa_object *o) {
475 record_stream *s = RECORD_STREAM(o);
478 record_stream_unlink(s);
480 pa_memblockq_free(s->memblockq);
484 /* Called from main context */
485 static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
486 record_stream *s = RECORD_STREAM(o);
487 record_stream_assert_ref(s);
494 case RECORD_STREAM_MESSAGE_POST_DATA:
496 /* We try to keep up to date with how many bytes are
497 * currently on the fly */
498 pa_atomic_sub(&s->on_the_fly, chunk->length);
500 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
501 /* pa_log_warn("Failed to push data into output queue."); */
505 if (!pa_pstream_is_pending(s->connection->pstream))
506 native_connection_send_memblock(s->connection);
514 /* Called from main context */
515 static void fix_record_buffer_attr_pre(record_stream *s) {
518 pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec;
522 /* This function will be called from the main thread, before as
523 * well as after the source output has been activated using
524 * pa_source_output_put()! That means it may not touch any
525 * ->thread_info data! */
527 frame_size = pa_frame_size(&s->source_output->sample_spec);
529 if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
530 s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
531 if (s->buffer_attr.maxlength <= 0)
532 s->buffer_attr.maxlength = (uint32_t) frame_size;
534 if (s->buffer_attr.fragsize == (uint32_t) -1)
535 s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
536 if (s->buffer_attr.fragsize <= 0)
537 s->buffer_attr.fragsize = (uint32_t) frame_size;
539 orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(s->buffer_attr.fragsize, &s->source_output->sample_spec);
541 if (s->early_requests) {
543 /* In early request mode we need to emulate the classic
544 * fragment-based playback model. We do this setting the source
545 * latency to the fragment size. */
547 source_usec = fragsize_usec;
549 } else if (s->adjust_latency) {
551 /* So, the user asked us to adjust the latency according to
552 * what the source can provide. Half the latency will be
553 * spent on the hw buffer, half of it in the async buffer
554 * queue we maintain for each client. */
556 source_usec = fragsize_usec/2;
560 /* Ok, the user didn't ask us to adjust the latency, hence we
563 source_usec = (pa_usec_t) -1;
566 if (source_usec != (pa_usec_t) -1)
567 s->configured_source_latency = pa_source_output_set_requested_latency(s->source_output, source_usec);
569 s->configured_source_latency = 0;
571 if (s->early_requests) {
573 /* Ok, we didn't necessarily get what we were asking for, so
574 * let's tell the user */
576 fragsize_usec = s->configured_source_latency;
578 } else if (s->adjust_latency) {
580 /* Now subtract what we actually got */
582 if (fragsize_usec >= s->configured_source_latency*2)
583 fragsize_usec -= s->configured_source_latency;
585 fragsize_usec = s->configured_source_latency;
588 if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) !=
589 pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec))
591 s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
593 if (s->buffer_attr.fragsize <= 0)
594 s->buffer_attr.fragsize = (uint32_t) frame_size;
597 /* Called from main context */
598 static void fix_record_buffer_attr_post(record_stream *s) {
603 /* This function will be called from the main thread, before as
604 * well as after the source output has been activated using
605 * pa_source_output_put()! That means it may not touch and
606 * ->thread_info data! */
608 base = pa_frame_size(&s->source_output->sample_spec);
610 s->buffer_attr.fragsize = (s->buffer_attr.fragsize/base)*base;
611 if (s->buffer_attr.fragsize <= 0)
612 s->buffer_attr.fragsize = base;
614 if (s->buffer_attr.fragsize > s->buffer_attr.maxlength)
615 s->buffer_attr.fragsize = s->buffer_attr.maxlength;
618 /* Called from main context */
619 static record_stream* record_stream_new(
620 pa_native_connection *c,
624 pa_bool_t peak_detect,
625 pa_buffer_attr *attr,
626 pa_source_output_flags_t flags,
628 pa_bool_t adjust_latency,
629 pa_sink_input *direct_on_input,
630 pa_bool_t early_requests,
634 pa_source_output *source_output = NULL;
635 pa_source_output_new_data data;
642 pa_source_output_new_data_init(&data);
644 pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
645 data.driver = __FILE__;
646 data.module = c->options->module;
647 data.client = c->client;
648 data.source = source;
649 data.direct_on_input = direct_on_input;
650 pa_source_output_new_data_set_sample_spec(&data, ss);
651 pa_source_output_new_data_set_channel_map(&data, map);
653 data.resample_method = PA_RESAMPLER_PEAKS;
656 *ret = -pa_source_output_new(&source_output, c->protocol->core, &data);
658 pa_source_output_new_data_done(&data);
663 s = pa_msgobject_new(record_stream);
664 s->parent.parent.free = record_stream_free;
665 s->parent.process_msg = record_stream_process_msg;
667 s->source_output = source_output;
668 s->buffer_attr = *attr;
669 s->adjust_latency = adjust_latency;
670 s->early_requests = early_requests;
671 pa_atomic_store(&s->on_the_fly, 0);
673 s->source_output->parent.process_msg = source_output_process_msg;
674 s->source_output->push = source_output_push_cb;
675 s->source_output->kill = source_output_kill_cb;
676 s->source_output->get_latency = source_output_get_latency_cb;
677 s->source_output->moving = source_output_moving_cb;
678 s->source_output->suspend = source_output_suspend_cb;
679 s->source_output->send_event = source_output_send_event_cb;
680 s->source_output->userdata = s;
682 fix_record_buffer_attr_pre(s);
684 s->memblockq = pa_memblockq_new(
686 s->buffer_attr.maxlength,
688 pa_frame_size(&source_output->sample_spec),
694 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
695 fix_record_buffer_attr_post(s);
697 *ss = s->source_output->sample_spec;
698 *map = s->source_output->channel_map;
700 pa_idxset_put(c->record_streams, s, &s->index);
702 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
703 ((double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) + (double) s->configured_source_latency) / PA_USEC_PER_MSEC,
704 (double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) / PA_USEC_PER_MSEC,
705 (double) s->configured_source_latency / PA_USEC_PER_MSEC);
707 pa_source_output_put(s->source_output);
711 /* Called from main context */
712 static void record_stream_send_killed(record_stream *r) {
714 record_stream_assert_ref(r);
716 t = pa_tagstruct_new(NULL, 0);
717 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
718 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
719 pa_tagstruct_putu32(t, r->index);
720 pa_pstream_send_tagstruct(r->connection->pstream, t);
723 /* Called from main context */
724 static void playback_stream_unlink(playback_stream *s) {
731 pa_sink_input_unlink(s->sink_input);
732 pa_sink_input_unref(s->sink_input);
733 s->sink_input = NULL;
736 if (s->drain_request)
737 pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
739 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
740 s->connection = NULL;
741 playback_stream_unref(s);
744 /* Called from main context */
745 static void playback_stream_free(pa_object* o) {
746 playback_stream *s = PLAYBACK_STREAM(o);
749 playback_stream_unlink(s);
751 pa_memblockq_free(s->memblockq);
755 /* Called from main context */
756 static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
757 playback_stream *s = PLAYBACK_STREAM(o);
758 playback_stream_assert_ref(s);
765 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
770 if ((l = pa_atomic_load(&s->missing)) <= 0)
773 if (pa_atomic_cmpxchg(&s->missing, l, 0))
777 t = pa_tagstruct_new(NULL, 0);
778 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
779 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
780 pa_tagstruct_putu32(t, s->index);
781 pa_tagstruct_putu32(t, (uint32_t) l);
782 pa_pstream_send_tagstruct(s->connection->pstream, t);
784 /* pa_log("Requesting %lu bytes", (unsigned long) l); */
788 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
791 /* pa_log("signalling underflow"); */
793 /* Report that we're empty */
794 t = pa_tagstruct_new(NULL, 0);
795 pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
796 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
797 pa_tagstruct_putu32(t, s->index);
798 pa_pstream_send_tagstruct(s->connection->pstream, t);
802 case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
805 /* Notify the user we're overflowed*/
806 t = pa_tagstruct_new(NULL, 0);
807 pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
808 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
809 pa_tagstruct_putu32(t, s->index);
810 pa_pstream_send_tagstruct(s->connection->pstream, t);
814 case PLAYBACK_STREAM_MESSAGE_STARTED:
816 if (s->connection->version >= 13) {
819 /* Notify the user we started playback */
820 t = pa_tagstruct_new(NULL, 0);
821 pa_tagstruct_putu32(t, PA_COMMAND_STARTED);
822 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
823 pa_tagstruct_putu32(t, s->index);
824 pa_pstream_send_tagstruct(s->connection->pstream, t);
829 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
830 pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
833 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH:
835 s->buffer_attr.tlength = (uint32_t) offset;
837 if (s->connection->version >= 15) {
840 t = pa_tagstruct_new(NULL, 0);
841 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
842 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
843 pa_tagstruct_putu32(t, s->index);
844 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
845 pa_tagstruct_putu32(t, s->buffer_attr.tlength);
846 pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
847 pa_tagstruct_putu32(t, s->buffer_attr.minreq);
848 pa_tagstruct_put_usec(t, s->configured_sink_latency);
849 pa_pstream_send_tagstruct(s->connection->pstream, t);
858 /* Called from main context */
859 static void fix_playback_buffer_attr(playback_stream *s) {
860 size_t frame_size, max_prebuf;
861 pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec;
865 /* pa_log("Client requested: maxlength=%li bytes tlength=%li bytes minreq=%li bytes prebuf=%li bytes", */
866 /* (long) s->buffer_attr.maxlength, */
867 /* (long) s->buffer_attr.tlength, */
868 /* (long) s->buffer_attr.minreq, */
869 /* (long) s->buffer_attr.prebuf); */
871 /* pa_log("Client requested: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms", */
872 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
873 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
874 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
875 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC)); */
877 /* This function will be called from the main thread, before as
878 * well as after the sink input has been activated using
879 * pa_sink_input_put()! That means it may not touch any
880 * ->thread_info data, such as the memblockq! */
882 frame_size = pa_frame_size(&s->sink_input->sample_spec);
884 if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
885 s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
886 if (s->buffer_attr.maxlength <= 0)
887 s->buffer_attr.maxlength = (uint32_t) frame_size;
889 if (s->buffer_attr.tlength == (uint32_t) -1)
890 s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
891 if (s->buffer_attr.tlength <= 0)
892 s->buffer_attr.tlength = (uint32_t) frame_size;
894 if (s->buffer_attr.minreq == (uint32_t) -1)
895 s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
896 if (s->buffer_attr.minreq <= 0)
897 s->buffer_attr.minreq = (uint32_t) frame_size;
899 if (s->buffer_attr.tlength < s->buffer_attr.minreq+frame_size)
900 s->buffer_attr.tlength = s->buffer_attr.minreq+(uint32_t) frame_size;
902 orig_tlength_usec = tlength_usec = pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec);
903 orig_minreq_usec = minreq_usec = pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec);
905 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
906 (double) tlength_usec / PA_USEC_PER_MSEC,
907 (double) minreq_usec / PA_USEC_PER_MSEC);
909 if (s->early_requests) {
911 /* In early request mode we need to emulate the classic
912 * fragment-based playback model. We do this setting the sink
913 * latency to the fragment size. */
915 sink_usec = minreq_usec;
916 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
918 } else if (s->adjust_latency) {
920 /* So, the user asked us to adjust the latency of the stream
921 * buffer according to the what the sink can provide. The
922 * tlength passed in shall be the overall latency. Roughly
923 * half the latency will be spent on the hw buffer, the other
924 * half of it in the async buffer queue we maintain for each
925 * client. In between we'll have a safety space of size
926 * 2*minreq. Why the 2*minreq? When the hw buffer is completey
927 * empty and needs to be filled, then our buffer must have
928 * enough data to fulfill this request immediatly and thus
929 * have at least the same tlength as the size of the hw
930 * buffer. It additionally needs space for 2 times minreq
931 * because if the buffer ran empty and a partial fillup
932 * happens immediately on the next iteration we need to be
933 * able to fulfill it and give the application also minreq
934 * time to fill it up again for the next request Makes 2 times
935 * minreq in plus.. */
937 if (tlength_usec > minreq_usec*2)
938 sink_usec = (tlength_usec - minreq_usec*2)/2;
942 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
946 /* Ok, the user didn't ask us to adjust the latency, but we
947 * still need to make sure that the parameters from the user
950 if (tlength_usec > minreq_usec*2)
951 sink_usec = (tlength_usec - minreq_usec*2);
955 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
958 s->configured_sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
960 if (s->early_requests) {
962 /* Ok, we didn't necessarily get what we were asking for, so
963 * let's tell the user */
965 minreq_usec = s->configured_sink_latency;
967 } else if (s->adjust_latency) {
969 /* Ok, we didn't necessarily get what we were asking for, so
970 * let's subtract from what we asked for for the remaining
973 if (tlength_usec >= s->configured_sink_latency)
974 tlength_usec -= s->configured_sink_latency;
977 /* FIXME: This is actually larger than necessary, since not all of
978 * the sink latency is actually rewritable. */
979 if (tlength_usec < s->configured_sink_latency + 2*minreq_usec)
980 tlength_usec = s->configured_sink_latency + 2*minreq_usec;
982 if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) !=
983 pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec))
984 s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec);
986 if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) !=
987 pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec))
988 s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
990 if (s->buffer_attr.minreq <= 0) {
991 s->buffer_attr.minreq = (uint32_t) frame_size;
992 s->buffer_attr.tlength += (uint32_t) frame_size*2;
995 if (s->buffer_attr.tlength <= s->buffer_attr.minreq)
996 s->buffer_attr.tlength = s->buffer_attr.minreq*2 + (uint32_t) frame_size;
998 max_prebuf = s->buffer_attr.tlength + (uint32_t)frame_size - s->buffer_attr.minreq;
1000 if (s->buffer_attr.prebuf == (uint32_t) -1 ||
1001 s->buffer_attr.prebuf > max_prebuf)
1002 s->buffer_attr.prebuf = max_prebuf;
1004 /* pa_log("Client accepted: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms", */
1005 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
1006 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
1007 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
1008 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC)); */
1011 /* Called from main context */
1012 static playback_stream* playback_stream_new(
1013 pa_native_connection *c,
1016 pa_channel_map *map,
1020 pa_bool_t muted_set,
1023 pa_sink_input_flags_t flags,
1025 pa_bool_t adjust_latency,
1026 pa_bool_t early_requests,
1027 pa_bool_t relative_volume,
1030 playback_stream *s, *ssync;
1031 pa_sink_input *sink_input = NULL;
1032 pa_memchunk silence;
1034 int64_t start_index;
1035 pa_sink_input_new_data data;
1043 /* Find syncid group */
1044 PA_IDXSET_FOREACH(ssync, c->output_streams, idx) {
1046 if (!playback_stream_isinstance(ssync))
1049 if (ssync->syncid == syncid)
1053 /* Synced streams must connect to the same sink */
1057 sink = ssync->sink_input->sink;
1058 else if (sink != ssync->sink_input->sink) {
1059 *ret = PA_ERR_INVALID;
1064 pa_sink_input_new_data_init(&data);
1066 pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
1067 data.driver = __FILE__;
1068 data.module = c->options->module;
1069 data.client = c->client;
1072 data.save_sink = TRUE;
1074 pa_sink_input_new_data_set_sample_spec(&data, ss);
1075 pa_sink_input_new_data_set_channel_map(&data, map);
1077 pa_sink_input_new_data_set_volume(&data, volume);
1078 data.volume_is_absolute = !relative_volume;
1079 data.save_volume = TRUE;
1082 pa_sink_input_new_data_set_muted(&data, muted);
1083 data.save_muted = TRUE;
1085 data.sync_base = ssync ? ssync->sink_input : NULL;
1088 *ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data);
1090 pa_sink_input_new_data_done(&data);
1095 s = pa_msgobject_new(playback_stream);
1096 s->parent.parent.parent.free = playback_stream_free;
1097 s->parent.parent.process_msg = playback_stream_process_msg;
1100 s->sink_input = sink_input;
1101 s->is_underrun = TRUE;
1102 s->drain_request = FALSE;
1103 pa_atomic_store(&s->missing, 0);
1104 s->buffer_attr = *a;
1105 s->adjust_latency = adjust_latency;
1106 s->early_requests = early_requests;
1107 pa_atomic_store(&s->seek_or_post_in_queue, 0);
1108 s->seek_windex = -1;
1110 s->sink_input->parent.process_msg = sink_input_process_msg;
1111 s->sink_input->pop = sink_input_pop_cb;
1112 s->sink_input->process_rewind = sink_input_process_rewind_cb;
1113 s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1114 s->sink_input->update_max_request = sink_input_update_max_request_cb;
1115 s->sink_input->kill = sink_input_kill_cb;
1116 s->sink_input->moving = sink_input_moving_cb;
1117 s->sink_input->suspend = sink_input_suspend_cb;
1118 s->sink_input->send_event = sink_input_send_event_cb;
1119 s->sink_input->userdata = s;
1121 start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
1123 fix_playback_buffer_attr(s);
1125 pa_sink_input_get_silence(sink_input, &silence);
1126 s->memblockq = pa_memblockq_new(
1128 s->buffer_attr.maxlength,
1129 s->buffer_attr.tlength,
1130 pa_frame_size(&sink_input->sample_spec),
1131 s->buffer_attr.prebuf,
1132 s->buffer_attr.minreq,
1135 pa_memblock_unref(silence.memblock);
1137 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1139 *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
1141 /* pa_log("missing original: %li", (long int) *missing); */
1143 *ss = s->sink_input->sample_spec;
1144 *map = s->sink_input->channel_map;
1146 pa_idxset_put(c->output_streams, s, &s->index);
1148 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1149 ((double) pa_bytes_to_usec(s->buffer_attr.tlength, &sink_input->sample_spec) + (double) s->configured_sink_latency) / PA_USEC_PER_MSEC,
1150 (double) pa_bytes_to_usec(s->buffer_attr.tlength-s->buffer_attr.minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1151 (double) pa_bytes_to_usec(s->buffer_attr.minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1152 (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
1154 pa_sink_input_put(s->sink_input);
1158 /* Called from IO context */
1159 static void playback_stream_request_bytes(playback_stream *s) {
1161 int previous_missing;
1163 playback_stream_assert_ref(s);
1165 m = pa_memblockq_pop_missing(s->memblockq);
1167 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
1168 /* (unsigned long) m, */
1169 /* pa_memblockq_get_tlength(s->memblockq), */
1170 /* pa_memblockq_get_minreq(s->memblockq), */
1171 /* pa_memblockq_get_length(s->memblockq), */
1172 /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
1177 /* pa_log("request_bytes(%lu)", (unsigned long) m); */
1179 previous_missing = pa_atomic_add(&s->missing, (int) m);
1180 minreq = pa_memblockq_get_minreq(s->memblockq);
1182 if (pa_memblockq_prebuf_active(s->memblockq) ||
1183 (previous_missing < (int) minreq && previous_missing + (int) m >= (int) minreq))
1184 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
1187 /* Called from main context */
1188 static void playback_stream_send_killed(playback_stream *p) {
1190 playback_stream_assert_ref(p);
1192 t = pa_tagstruct_new(NULL, 0);
1193 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
1194 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1195 pa_tagstruct_putu32(t, p->index);
1196 pa_pstream_send_tagstruct(p->connection->pstream, t);
1199 /* Called from main context */
1200 static int native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
1201 pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1202 pa_native_connection_assert_ref(c);
1209 case CONNECTION_MESSAGE_REVOKE:
1210 pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
1213 case CONNECTION_MESSAGE_RELEASE:
1214 pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
1221 /* Called from main context */
1222 static void native_connection_unlink(pa_native_connection *c) {
1231 pa_hook_fire(&c->protocol->hooks[PA_NATIVE_HOOK_CONNECTION_UNLINK], c);
1234 pa_native_options_unref(c->options);
1236 while ((r = pa_idxset_first(c->record_streams, NULL)))
1237 record_stream_unlink(r);
1239 while ((o = pa_idxset_first(c->output_streams, NULL)))
1240 if (playback_stream_isinstance(o))
1241 playback_stream_unlink(PLAYBACK_STREAM(o));
1243 upload_stream_unlink(UPLOAD_STREAM(o));
1245 if (c->subscription)
1246 pa_subscription_free(c->subscription);
1249 pa_pstream_unlink(c->pstream);
1251 if (c->auth_timeout_event) {
1252 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
1253 c->auth_timeout_event = NULL;
1256 pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
1258 pa_native_connection_unref(c);
1261 /* Called from main context */
1262 static void native_connection_free(pa_object *o) {
1263 pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1267 native_connection_unlink(c);
1269 pa_idxset_free(c->record_streams, NULL, NULL);
1270 pa_idxset_free(c->output_streams, NULL, NULL);
1272 pa_pdispatch_unref(c->pdispatch);
1273 pa_pstream_unref(c->pstream);
1274 pa_client_free(c->client);
1279 /* Called from main context */
1280 static void native_connection_send_memblock(pa_native_connection *c) {
1284 start = PA_IDXSET_INVALID;
1288 if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
1291 if (start == PA_IDXSET_INVALID)
1292 start = c->rrobin_index;
1293 else if (start == c->rrobin_index)
1296 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
1297 pa_memchunk schunk = chunk;
1299 if (schunk.length > r->buffer_attr.fragsize)
1300 schunk.length = r->buffer_attr.fragsize;
1302 pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
1304 pa_memblockq_drop(r->memblockq, schunk.length);
1305 pa_memblock_unref(schunk.memblock);
1312 /*** sink input callbacks ***/
1314 /* Called from thread context */
1315 static void handle_seek(playback_stream *s, int64_t indexw) {
1316 playback_stream_assert_ref(s);
1318 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1320 if (s->sink_input->thread_info.underrun_for > 0) {
1322 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1324 if (pa_memblockq_is_readable(s->memblockq)) {
1326 /* We just ended an underrun, let's ask the sink
1327 * for a complete rewind rewrite */
1329 pa_log_debug("Requesting rewind due to end of underrun.");
1330 pa_sink_input_request_rewind(s->sink_input,
1331 (size_t) (s->sink_input->thread_info.underrun_for == (uint64_t) -1 ? 0 :
1332 s->sink_input->thread_info.underrun_for),
1333 FALSE, TRUE, FALSE);
1339 indexr = pa_memblockq_get_read_index(s->memblockq);
1341 if (indexw < indexr) {
1342 /* OK, the sink already asked for this data, so
1343 * let's have it usk us again */
1345 pa_log_debug("Requesting rewind due to rewrite.");
1346 pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE, FALSE);
1350 playback_stream_request_bytes(s);
1353 static void flush_write_no_account(pa_memblockq *q) {
1354 pa_memblockq_flush_write(q, FALSE);
1357 /* Called from thread context */
1358 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1359 pa_sink_input *i = PA_SINK_INPUT(o);
1362 pa_sink_input_assert_ref(i);
1363 s = PLAYBACK_STREAM(i->userdata);
1364 playback_stream_assert_ref(s);
1368 case SINK_INPUT_MESSAGE_SEEK:
1369 case SINK_INPUT_MESSAGE_POST_DATA: {
1370 int64_t windex = pa_memblockq_get_write_index(s->memblockq);
1372 if (code == SINK_INPUT_MESSAGE_SEEK) {
1373 /* The client side is incapable of accounting correctly
1374 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1375 * able to deal with that. */
1377 pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata), PA_PTR_TO_UINT(userdata) == PA_SEEK_RELATIVE);
1378 windex = PA_MIN(windex, pa_memblockq_get_write_index(s->memblockq));
1381 if (chunk && pa_memblockq_push_align(s->memblockq, chunk) < 0) {
1382 if (pa_log_ratelimit(PA_LOG_WARN))
1383 pa_log_warn("Failed to push data into queue");
1384 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
1385 pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, TRUE);
1388 /* If more data is in queue, we rewind later instead. */
1389 if (s->seek_windex != -1)
1390 windex = PA_MIN(windex, s->seek_windex);
1391 if (pa_atomic_dec(&s->seek_or_post_in_queue) > 1)
1392 s->seek_windex = windex;
1394 s->seek_windex = -1;
1395 handle_seek(s, windex);
1400 case SINK_INPUT_MESSAGE_DRAIN:
1401 case SINK_INPUT_MESSAGE_FLUSH:
1402 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1403 case SINK_INPUT_MESSAGE_TRIGGER: {
1406 pa_sink_input *isync;
1407 void (*func)(pa_memblockq *bq);
1410 case SINK_INPUT_MESSAGE_FLUSH:
1411 func = flush_write_no_account;
1414 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1415 func = pa_memblockq_prebuf_force;
1418 case SINK_INPUT_MESSAGE_DRAIN:
1419 case SINK_INPUT_MESSAGE_TRIGGER:
1420 func = pa_memblockq_prebuf_disable;
1424 pa_assert_not_reached();
1427 windex = pa_memblockq_get_write_index(s->memblockq);
1429 handle_seek(s, windex);
1431 /* Do the same for all other members in the sync group */
1432 for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
1433 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1434 windex = pa_memblockq_get_write_index(ssync->memblockq);
1435 func(ssync->memblockq);
1436 handle_seek(ssync, windex);
1439 for (isync = i->sync_next; isync; isync = isync->sync_next) {
1440 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1441 windex = pa_memblockq_get_write_index(ssync->memblockq);
1442 func(ssync->memblockq);
1443 handle_seek(ssync, windex);
1446 if (code == SINK_INPUT_MESSAGE_DRAIN) {
1447 if (!pa_memblockq_is_readable(s->memblockq))
1448 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
1450 s->drain_tag = PA_PTR_TO_UINT(userdata);
1451 s->drain_request = TRUE;
1458 case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
1459 /* Atomically get a snapshot of all timing parameters... */
1460 s->read_index = pa_memblockq_get_read_index(s->memblockq);
1461 s->write_index = pa_memblockq_get_write_index(s->memblockq);
1462 s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
1463 s->current_sink_latency = pa_sink_get_latency_within_thread(s->sink_input->sink);
1464 s->underrun_for = s->sink_input->thread_info.underrun_for;
1465 s->playing_for = s->sink_input->thread_info.playing_for;
1469 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1472 windex = pa_memblockq_get_write_index(s->memblockq);
1474 pa_memblockq_prebuf_force(s->memblockq);
1476 handle_seek(s, windex);
1478 /* Fall through to the default handler */
1482 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1483 pa_usec_t *r = userdata;
1485 *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
1487 /* Fall through, the default handler will add in the extra
1488 * latency added by the resampler */
1492 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR: {
1493 pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1494 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1499 return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1502 /* Called from thread context */
1503 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
1506 pa_sink_input_assert_ref(i);
1507 s = PLAYBACK_STREAM(i->userdata);
1508 playback_stream_assert_ref(s);
1511 /* pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1513 if (pa_memblockq_is_readable(s->memblockq))
1514 s->is_underrun = FALSE;
1516 if (!s->is_underrun)
1517 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));
1519 if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
1520 s->drain_request = FALSE;
1521 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);
1522 } else if (!s->is_underrun)
1523 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
1525 s->is_underrun = TRUE;
1527 playback_stream_request_bytes(s);
1530 /* This call will not fail with prebuf=0, hence we check for
1531 underrun explicitly above */
1532 if (pa_memblockq_peek(s->memblockq, chunk) < 0)
1535 chunk->length = PA_MIN(nbytes, chunk->length);
1537 if (i->thread_info.underrun_for > 0)
1538 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
1540 pa_memblockq_drop(s->memblockq, chunk->length);
1541 playback_stream_request_bytes(s);
1546 /* Called from thread context */
1547 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1550 pa_sink_input_assert_ref(i);
1551 s = PLAYBACK_STREAM(i->userdata);
1552 playback_stream_assert_ref(s);
1554 /* If we are in an underrun, then we don't rewind */
1555 if (i->thread_info.underrun_for > 0)
1558 pa_memblockq_rewind(s->memblockq, nbytes);
1561 /* Called from thread context */
1562 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1565 pa_sink_input_assert_ref(i);
1566 s = PLAYBACK_STREAM(i->userdata);
1567 playback_stream_assert_ref(s);
1569 pa_memblockq_set_maxrewind(s->memblockq, nbytes);
1572 /* Called from thread context */
1573 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
1575 size_t new_tlength, old_tlength;
1577 pa_sink_input_assert_ref(i);
1578 s = PLAYBACK_STREAM(i->userdata);
1579 playback_stream_assert_ref(s);
1581 old_tlength = pa_memblockq_get_tlength(s->memblockq);
1582 new_tlength = nbytes+2*pa_memblockq_get_minreq(s->memblockq);
1584 if (old_tlength < new_tlength) {
1585 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength, new_tlength);
1586 pa_memblockq_set_tlength(s->memblockq, new_tlength);
1587 new_tlength = pa_memblockq_get_tlength(s->memblockq);
1589 if (new_tlength == old_tlength)
1590 pa_log_debug("Failed to increase tlength");
1592 pa_log_debug("Notifying client about increased tlength");
1593 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);
1598 /* Called from main context */
1599 static void sink_input_kill_cb(pa_sink_input *i) {
1602 pa_sink_input_assert_ref(i);
1603 s = PLAYBACK_STREAM(i->userdata);
1604 playback_stream_assert_ref(s);
1606 playback_stream_send_killed(s);
1607 playback_stream_unlink(s);
1610 /* Called from main context */
1611 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl) {
1615 pa_sink_input_assert_ref(i);
1616 s = PLAYBACK_STREAM(i->userdata);
1617 playback_stream_assert_ref(s);
1619 if (s->connection->version < 15)
1622 t = pa_tagstruct_new(NULL, 0);
1623 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_EVENT);
1624 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1625 pa_tagstruct_putu32(t, s->index);
1626 pa_tagstruct_puts(t, event);
1627 pa_tagstruct_put_proplist(t, pl);
1628 pa_pstream_send_tagstruct(s->connection->pstream, t);
1631 /* Called from main context */
1632 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
1636 pa_sink_input_assert_ref(i);
1637 s = PLAYBACK_STREAM(i->userdata);
1638 playback_stream_assert_ref(s);
1640 if (s->connection->version < 12)
1643 t = pa_tagstruct_new(NULL, 0);
1644 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED);
1645 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1646 pa_tagstruct_putu32(t, s->index);
1647 pa_tagstruct_put_boolean(t, suspend);
1648 pa_pstream_send_tagstruct(s->connection->pstream, t);
1651 /* Called from main context */
1652 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1656 pa_sink_input_assert_ref(i);
1657 s = PLAYBACK_STREAM(i->userdata);
1658 playback_stream_assert_ref(s);
1663 fix_playback_buffer_attr(s);
1664 pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1665 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1667 if (s->connection->version < 12)
1670 t = pa_tagstruct_new(NULL, 0);
1671 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED);
1672 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1673 pa_tagstruct_putu32(t, s->index);
1674 pa_tagstruct_putu32(t, dest->index);
1675 pa_tagstruct_puts(t, dest->name);
1676 pa_tagstruct_put_boolean(t, pa_sink_get_state(dest) == PA_SINK_SUSPENDED);
1678 if (s->connection->version >= 13) {
1679 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1680 pa_tagstruct_putu32(t, s->buffer_attr.tlength);
1681 pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
1682 pa_tagstruct_putu32(t, s->buffer_attr.minreq);
1683 pa_tagstruct_put_usec(t, s->configured_sink_latency);
1686 pa_pstream_send_tagstruct(s->connection->pstream, t);
1689 /*** source_output callbacks ***/
1691 /* Called from thread context */
1692 static int source_output_process_msg(pa_msgobject *_o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1693 pa_source_output *o = PA_SOURCE_OUTPUT(_o);
1696 pa_source_output_assert_ref(o);
1697 s = RECORD_STREAM(o->userdata);
1698 record_stream_assert_ref(s);
1701 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY:
1702 /* Atomically get a snapshot of all timing parameters... */
1703 s->current_monitor_latency = o->source->monitor_of ? pa_sink_get_latency_within_thread(o->source->monitor_of) : 0;
1704 s->current_source_latency = pa_source_get_latency_within_thread(o->source);
1705 s->on_the_fly_snapshot = pa_atomic_load(&s->on_the_fly);
1709 return pa_source_output_process_msg(_o, code, userdata, offset, chunk);
1712 /* Called from thread context */
1713 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1716 pa_source_output_assert_ref(o);
1717 s = RECORD_STREAM(o->userdata);
1718 record_stream_assert_ref(s);
1721 pa_atomic_add(&s->on_the_fly, chunk->length);
1722 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1725 static void source_output_kill_cb(pa_source_output *o) {
1728 pa_source_output_assert_ref(o);
1729 s = RECORD_STREAM(o->userdata);
1730 record_stream_assert_ref(s);
1732 record_stream_send_killed(s);
1733 record_stream_unlink(s);
1736 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1739 pa_source_output_assert_ref(o);
1740 s = RECORD_STREAM(o->userdata);
1741 record_stream_assert_ref(s);
1743 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1745 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
1748 /* Called from main context */
1749 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl) {
1753 pa_source_output_assert_ref(o);
1754 s = RECORD_STREAM(o->userdata);
1755 record_stream_assert_ref(s);
1757 if (s->connection->version < 15)
1760 t = pa_tagstruct_new(NULL, 0);
1761 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_EVENT);
1762 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1763 pa_tagstruct_putu32(t, s->index);
1764 pa_tagstruct_puts(t, event);
1765 pa_tagstruct_put_proplist(t, pl);
1766 pa_pstream_send_tagstruct(s->connection->pstream, t);
1769 /* Called from main context */
1770 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
1774 pa_source_output_assert_ref(o);
1775 s = RECORD_STREAM(o->userdata);
1776 record_stream_assert_ref(s);
1778 if (s->connection->version < 12)
1781 t = pa_tagstruct_new(NULL, 0);
1782 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED);
1783 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1784 pa_tagstruct_putu32(t, s->index);
1785 pa_tagstruct_put_boolean(t, suspend);
1786 pa_pstream_send_tagstruct(s->connection->pstream, t);
1789 /* Called from main context */
1790 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
1794 pa_source_output_assert_ref(o);
1795 s = RECORD_STREAM(o->userdata);
1796 record_stream_assert_ref(s);
1801 fix_record_buffer_attr_pre(s);
1802 pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
1803 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1804 fix_record_buffer_attr_post(s);
1806 if (s->connection->version < 12)
1809 t = pa_tagstruct_new(NULL, 0);
1810 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED);
1811 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1812 pa_tagstruct_putu32(t, s->index);
1813 pa_tagstruct_putu32(t, dest->index);
1814 pa_tagstruct_puts(t, dest->name);
1815 pa_tagstruct_put_boolean(t, pa_source_get_state(dest) == PA_SOURCE_SUSPENDED);
1817 if (s->connection->version >= 13) {
1818 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1819 pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
1820 pa_tagstruct_put_usec(t, s->configured_source_latency);
1823 pa_pstream_send_tagstruct(s->connection->pstream, t);
1826 /*** pdispatch callbacks ***/
1828 static void protocol_error(pa_native_connection *c) {
1829 pa_log("protocol error, kicking client");
1830 native_connection_unlink(c);
1833 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1834 if (!(expression)) { \
1835 pa_pstream_send_error((pstream), (tag), (error)); \
1840 static pa_tagstruct *reply_new(uint32_t tag) {
1841 pa_tagstruct *reply;
1843 reply = pa_tagstruct_new(NULL, 0);
1844 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1845 pa_tagstruct_putu32(reply, tag);
1849 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1850 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
1852 uint32_t sink_index, syncid, missing;
1853 pa_buffer_attr attr;
1854 const char *name = NULL, *sink_name;
1857 pa_tagstruct *reply;
1858 pa_sink *sink = NULL;
1866 fix_channels = FALSE,
1868 variable_rate = FALSE,
1870 adjust_latency = FALSE,
1871 early_requests = FALSE,
1872 dont_inhibit_auto_suspend = FALSE,
1874 fail_on_suspend = FALSE,
1875 relative_volume = FALSE,
1876 passthrough = FALSE;
1878 pa_sink_input_flags_t flags = 0;
1880 pa_bool_t volume_set = TRUE;
1881 int ret = PA_ERR_INVALID;
1883 pa_native_connection_assert_ref(c);
1885 memset(&attr, 0, sizeof(attr));
1887 if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
1890 PA_TAG_SAMPLE_SPEC, &ss,
1891 PA_TAG_CHANNEL_MAP, &map,
1892 PA_TAG_U32, &sink_index,
1893 PA_TAG_STRING, &sink_name,
1894 PA_TAG_U32, &attr.maxlength,
1895 PA_TAG_BOOLEAN, &corked,
1896 PA_TAG_U32, &attr.tlength,
1897 PA_TAG_U32, &attr.prebuf,
1898 PA_TAG_U32, &attr.minreq,
1899 PA_TAG_U32, &syncid,
1900 PA_TAG_CVOLUME, &volume,
1901 PA_TAG_INVALID) < 0) {
1907 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1908 CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
1909 CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
1910 CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
1911 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1912 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1913 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
1914 CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
1916 p = pa_proplist_new();
1919 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
1921 if (c->version >= 12) {
1922 /* Since 0.9.8 the user can ask for a couple of additional flags */
1924 if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
1925 pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
1926 pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
1927 pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
1928 pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
1929 pa_tagstruct_get_boolean(t, &no_move) < 0 ||
1930 pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
1933 pa_proplist_free(p);
1938 if (c->version >= 13) {
1940 if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
1941 pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
1942 pa_tagstruct_get_proplist(t, p) < 0) {
1944 pa_proplist_free(p);
1949 if (c->version >= 14) {
1951 if (pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
1952 pa_tagstruct_get_boolean(t, &early_requests) < 0) {
1954 pa_proplist_free(p);
1959 if (c->version >= 15) {
1961 if (pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
1962 pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
1963 pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
1965 pa_proplist_free(p);
1970 if (c->version >= 17) {
1972 if (pa_tagstruct_get_boolean(t, &relative_volume) < 0) {
1974 pa_proplist_free(p);
1979 if (c->version >= 18) {
1981 if (pa_tagstruct_get_boolean(t, &passthrough) < 0 ) {
1983 pa_proplist_free(p);
1988 if (!pa_tagstruct_eof(t)) {
1990 pa_proplist_free(p);
1994 if (sink_index != PA_INVALID_INDEX) {
1996 if (!(sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index))) {
1997 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1998 pa_proplist_free(p);
2002 } else if (sink_name) {
2004 if (!(sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK))) {
2005 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2006 pa_proplist_free(p);
2012 (corked ? PA_SINK_INPUT_START_CORKED : 0) |
2013 (no_remap ? PA_SINK_INPUT_NO_REMAP : 0) |
2014 (no_remix ? PA_SINK_INPUT_NO_REMIX : 0) |
2015 (fix_format ? PA_SINK_INPUT_FIX_FORMAT : 0) |
2016 (fix_rate ? PA_SINK_INPUT_FIX_RATE : 0) |
2017 (fix_channels ? PA_SINK_INPUT_FIX_CHANNELS : 0) |
2018 (no_move ? PA_SINK_INPUT_DONT_MOVE : 0) |
2019 (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0) |
2020 (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2021 (fail_on_suspend ? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND : 0) |
2022 (passthrough ? PA_SINK_INPUT_PASSTHROUGH : 0);
2024 /* Only since protocol version 15 there's a seperate muted_set
2025 * flag. For older versions we synthesize it here */
2026 muted_set = muted_set || muted;
2028 s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, relative_volume, &ret);
2029 pa_proplist_free(p);
2031 CHECK_VALIDITY(c->pstream, s, tag, ret);
2033 reply = reply_new(tag);
2034 pa_tagstruct_putu32(reply, s->index);
2035 pa_assert(s->sink_input);
2036 pa_tagstruct_putu32(reply, s->sink_input->index);
2037 pa_tagstruct_putu32(reply, missing);
2039 /* pa_log("initial request is %u", missing); */
2041 if (c->version >= 9) {
2042 /* Since 0.9.0 we support sending the buffer metrics back to the client */
2044 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2045 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.tlength);
2046 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.prebuf);
2047 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.minreq);
2050 if (c->version >= 12) {
2051 /* Since 0.9.8 we support sending the chosen sample
2052 * spec/channel map/device/suspend status back to the
2055 pa_tagstruct_put_sample_spec(reply, &ss);
2056 pa_tagstruct_put_channel_map(reply, &map);
2058 pa_tagstruct_putu32(reply, s->sink_input->sink->index);
2059 pa_tagstruct_puts(reply, s->sink_input->sink->name);
2061 pa_tagstruct_put_boolean(reply, pa_sink_get_state(s->sink_input->sink) == PA_SINK_SUSPENDED);
2064 if (c->version >= 13)
2065 pa_tagstruct_put_usec(reply, s->configured_sink_latency);
2067 pa_pstream_send_tagstruct(c->pstream, reply);
2070 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2071 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2074 pa_native_connection_assert_ref(c);
2077 if (pa_tagstruct_getu32(t, &channel) < 0 ||
2078 !pa_tagstruct_eof(t)) {
2083 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2087 case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
2089 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
2090 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2094 playback_stream_unlink(s);
2098 case PA_COMMAND_DELETE_RECORD_STREAM: {
2100 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
2101 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2105 record_stream_unlink(s);
2109 case PA_COMMAND_DELETE_UPLOAD_STREAM: {
2112 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
2113 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2117 upload_stream_unlink(s);
2122 pa_assert_not_reached();
2125 pa_pstream_send_simple_ack(c->pstream, tag);
2128 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2129 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2131 pa_buffer_attr attr;
2132 uint32_t source_index;
2133 const char *name = NULL, *source_name;
2136 pa_tagstruct *reply;
2137 pa_source *source = NULL;
2144 fix_channels = FALSE,
2146 variable_rate = FALSE,
2147 adjust_latency = FALSE,
2148 peak_detect = FALSE,
2149 early_requests = FALSE,
2150 dont_inhibit_auto_suspend = FALSE,
2151 fail_on_suspend = FALSE;
2152 pa_source_output_flags_t flags = 0;
2154 uint32_t direct_on_input_idx = PA_INVALID_INDEX;
2155 pa_sink_input *direct_on_input = NULL;
2156 int ret = PA_ERR_INVALID;
2158 pa_native_connection_assert_ref(c);
2161 memset(&attr, 0, sizeof(attr));
2163 if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
2164 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2165 pa_tagstruct_get_channel_map(t, &map) < 0 ||
2166 pa_tagstruct_getu32(t, &source_index) < 0 ||
2167 pa_tagstruct_gets(t, &source_name) < 0 ||
2168 pa_tagstruct_getu32(t, &attr.maxlength) < 0 ||
2169 pa_tagstruct_get_boolean(t, &corked) < 0 ||
2170 pa_tagstruct_getu32(t, &attr.fragsize) < 0) {
2175 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2176 CHECK_VALIDITY(c->pstream, !source_name || pa_namereg_is_valid_name_or_wildcard(source_name, PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
2177 CHECK_VALIDITY(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID);
2178 CHECK_VALIDITY(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2179 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2180 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2181 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2183 p = pa_proplist_new();
2186 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2188 if (c->version >= 12) {
2189 /* Since 0.9.8 the user can ask for a couple of additional flags */
2191 if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
2192 pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
2193 pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
2194 pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
2195 pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
2196 pa_tagstruct_get_boolean(t, &no_move) < 0 ||
2197 pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
2200 pa_proplist_free(p);
2205 if (c->version >= 13) {
2207 if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
2208 pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
2209 pa_tagstruct_get_proplist(t, p) < 0 ||
2210 pa_tagstruct_getu32(t, &direct_on_input_idx) < 0) {
2212 pa_proplist_free(p);
2217 if (c->version >= 14) {
2219 if (pa_tagstruct_get_boolean(t, &early_requests) < 0) {
2221 pa_proplist_free(p);
2226 if (c->version >= 15) {
2228 if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
2229 pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
2231 pa_proplist_free(p);
2236 if (!pa_tagstruct_eof(t)) {
2238 pa_proplist_free(p);
2242 if (source_index != PA_INVALID_INDEX) {
2244 if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
2245 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2246 pa_proplist_free(p);
2250 } else if (source_name) {
2252 if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE))) {
2253 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2254 pa_proplist_free(p);
2259 if (direct_on_input_idx != PA_INVALID_INDEX) {
2261 if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
2262 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2263 pa_proplist_free(p);
2269 (corked ? PA_SOURCE_OUTPUT_START_CORKED : 0) |
2270 (no_remap ? PA_SOURCE_OUTPUT_NO_REMAP : 0) |
2271 (no_remix ? PA_SOURCE_OUTPUT_NO_REMIX : 0) |
2272 (fix_format ? PA_SOURCE_OUTPUT_FIX_FORMAT : 0) |
2273 (fix_rate ? PA_SOURCE_OUTPUT_FIX_RATE : 0) |
2274 (fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
2275 (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
2276 (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
2277 (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2278 (fail_on_suspend ? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND : 0);
2280 s = record_stream_new(c, source, &ss, &map, peak_detect, &attr, flags, p, adjust_latency, direct_on_input, early_requests, &ret);
2281 pa_proplist_free(p);
2283 CHECK_VALIDITY(c->pstream, s, tag, ret);
2285 reply = reply_new(tag);
2286 pa_tagstruct_putu32(reply, s->index);
2287 pa_assert(s->source_output);
2288 pa_tagstruct_putu32(reply, s->source_output->index);
2290 if (c->version >= 9) {
2291 /* Since 0.9 we support sending the buffer metrics back to the client */
2293 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2294 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.fragsize);
2297 if (c->version >= 12) {
2298 /* Since 0.9.8 we support sending the chosen sample
2299 * spec/channel map/device/suspend status back to the
2302 pa_tagstruct_put_sample_spec(reply, &ss);
2303 pa_tagstruct_put_channel_map(reply, &map);
2305 pa_tagstruct_putu32(reply, s->source_output->source->index);
2306 pa_tagstruct_puts(reply, s->source_output->source->name);
2308 pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED);
2311 if (c->version >= 13)
2312 pa_tagstruct_put_usec(reply, s->configured_source_latency);
2314 pa_pstream_send_tagstruct(c->pstream, reply);
2317 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2318 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2321 pa_native_connection_assert_ref(c);
2324 if (!pa_tagstruct_eof(t)) {
2329 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2330 ret = pa_core_exit(c->protocol->core, FALSE, 0);
2331 CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
2333 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)));
2335 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
2338 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2339 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2341 pa_tagstruct *reply;
2342 pa_bool_t shm_on_remote = FALSE, do_shm;
2344 pa_native_connection_assert_ref(c);
2347 if (pa_tagstruct_getu32(t, &c->version) < 0 ||
2348 pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
2349 !pa_tagstruct_eof(t)) {
2354 /* Minimum supported version */
2355 if (c->version < 8) {
2356 pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
2360 /* Starting with protocol version 13 the MSB of the version tag
2361 reflects if shm is available for this pa_native_connection or
2363 if (c->version >= 13) {
2364 shm_on_remote = !!(c->version & 0x80000000U);
2365 c->version &= 0x7FFFFFFFU;
2368 pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
2370 pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
2372 if (!c->authorized) {
2373 pa_bool_t success = FALSE;
2376 const pa_creds *creds;
2378 if ((creds = pa_pdispatch_creds(pd))) {
2379 if (creds->uid == getuid())
2381 else if (c->options->auth_group) {
2385 if ((gid = pa_get_gid_of_group(c->options->auth_group)) == (gid_t) -1)
2386 pa_log_warn("Failed to get GID of group '%s'", c->options->auth_group);
2387 else if (gid == creds->gid)
2391 if ((r = pa_uid_in_group(creds->uid, c->options->auth_group)) < 0)
2392 pa_log_warn("Failed to check group membership.");
2398 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2399 (unsigned long) creds->uid,
2400 (unsigned long) creds->gid,
2405 if (!success && c->options->auth_cookie) {
2408 if ((ac = pa_auth_cookie_read(c->options->auth_cookie, PA_NATIVE_COOKIE_LENGTH)))
2409 if (memcmp(ac, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
2414 pa_log_warn("Denied access to client with invalid authorization data.");
2415 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2419 c->authorized = TRUE;
2420 if (c->auth_timeout_event) {
2421 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
2422 c->auth_timeout_event = NULL;
2426 /* Enable shared memory support if possible */
2428 pa_mempool_is_shared(c->protocol->core->mempool) &&
2431 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm));
2434 if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
2439 /* Only enable SHM if both sides are owned by the same
2440 * user. This is a security measure because otherwise data
2441 * private to the user might leak. */
2443 const pa_creds *creds;
2444 if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
2449 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
2450 pa_pstream_enable_shm(c->pstream, do_shm);
2452 reply = reply_new(tag);
2453 pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0));
2457 /* SHM support is only enabled after both sides made sure they are the same user. */
2461 ucred.uid = getuid();
2462 ucred.gid = getgid();
2464 pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
2467 pa_pstream_send_tagstruct(c->pstream, reply);
2471 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2472 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2473 const char *name = NULL;
2475 pa_tagstruct *reply;
2477 pa_native_connection_assert_ref(c);
2480 p = pa_proplist_new();
2482 if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
2483 (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2484 !pa_tagstruct_eof(t)) {
2487 pa_proplist_free(p);
2492 if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
2493 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2494 pa_proplist_free(p);
2498 pa_client_update_proplist(c->client, PA_UPDATE_REPLACE, p);
2499 pa_proplist_free(p);
2501 reply = reply_new(tag);
2503 if (c->version >= 13)
2504 pa_tagstruct_putu32(reply, c->client->index);
2506 pa_pstream_send_tagstruct(c->pstream, reply);
2509 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2510 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2512 uint32_t idx = PA_IDXSET_INVALID;
2514 pa_native_connection_assert_ref(c);
2517 if (pa_tagstruct_gets(t, &name) < 0 ||
2518 !pa_tagstruct_eof(t)) {
2523 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2524 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_LOOKUP_SINK ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
2526 if (command == PA_COMMAND_LOOKUP_SINK) {
2528 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK)))
2532 pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
2533 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE)))
2534 idx = source->index;
2537 if (idx == PA_IDXSET_INVALID)
2538 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2540 pa_tagstruct *reply;
2541 reply = reply_new(tag);
2542 pa_tagstruct_putu32(reply, idx);
2543 pa_pstream_send_tagstruct(c->pstream, reply);
2547 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2548 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2552 pa_native_connection_assert_ref(c);
2555 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2556 !pa_tagstruct_eof(t)) {
2561 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2562 s = pa_idxset_get_by_index(c->output_streams, idx);
2563 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2564 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2566 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);
2569 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2570 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2571 pa_tagstruct *reply;
2572 const pa_mempool_stat *stat;
2574 pa_native_connection_assert_ref(c);
2577 if (!pa_tagstruct_eof(t)) {
2582 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2584 stat = pa_mempool_get_stat(c->protocol->core->mempool);
2586 reply = reply_new(tag);
2587 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
2588 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
2589 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
2590 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
2591 pa_tagstruct_putu32(reply, (uint32_t) pa_scache_total_size(c->protocol->core));
2592 pa_pstream_send_tagstruct(c->pstream, reply);
2595 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2596 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2597 pa_tagstruct *reply;
2599 struct timeval tv, now;
2602 pa_native_connection_assert_ref(c);
2605 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2606 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2607 !pa_tagstruct_eof(t)) {
2612 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2613 s = pa_idxset_get_by_index(c->output_streams, idx);
2614 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2615 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2617 /* Get an atomic snapshot of all timing parameters */
2618 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);
2620 reply = reply_new(tag);
2621 pa_tagstruct_put_usec(reply,
2622 s->current_sink_latency +
2623 pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sink->sample_spec));
2624 pa_tagstruct_put_usec(reply, 0);
2625 pa_tagstruct_put_boolean(reply,
2626 s->playing_for > 0 &&
2627 pa_sink_get_state(s->sink_input->sink) == PA_SINK_RUNNING &&
2628 pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
2629 pa_tagstruct_put_timeval(reply, &tv);
2630 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2631 pa_tagstruct_puts64(reply, s->write_index);
2632 pa_tagstruct_puts64(reply, s->read_index);
2634 if (c->version >= 13) {
2635 pa_tagstruct_putu64(reply, s->underrun_for);
2636 pa_tagstruct_putu64(reply, s->playing_for);
2639 pa_pstream_send_tagstruct(c->pstream, reply);
2642 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2643 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2644 pa_tagstruct *reply;
2646 struct timeval tv, now;
2649 pa_native_connection_assert_ref(c);
2652 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2653 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2654 !pa_tagstruct_eof(t)) {
2659 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2660 s = pa_idxset_get_by_index(c->record_streams, idx);
2661 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2663 /* Get an atomic snapshot of all timing parameters */
2664 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);
2666 reply = reply_new(tag);
2667 pa_tagstruct_put_usec(reply, s->current_monitor_latency);
2668 pa_tagstruct_put_usec(reply,
2669 s->current_source_latency +
2670 pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->source->sample_spec));
2671 pa_tagstruct_put_boolean(reply,
2672 pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING &&
2673 pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING);
2674 pa_tagstruct_put_timeval(reply, &tv);
2675 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2676 pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
2677 pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
2678 pa_pstream_send_tagstruct(c->pstream, reply);
2681 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2682 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2685 const char *name = NULL;
2688 pa_tagstruct *reply;
2691 pa_native_connection_assert_ref(c);
2694 if (pa_tagstruct_gets(t, &name) < 0 ||
2695 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2696 pa_tagstruct_get_channel_map(t, &map) < 0 ||
2697 pa_tagstruct_getu32(t, &length) < 0) {
2702 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2703 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2704 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2705 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2706 CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
2707 CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
2709 p = pa_proplist_new();
2711 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2712 !pa_tagstruct_eof(t)) {
2715 pa_proplist_free(p);
2719 if (c->version < 13)
2720 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2722 if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID)))
2723 name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME);
2725 if (!name || !pa_namereg_is_valid_name(name)) {
2726 pa_proplist_free(p);
2727 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
2730 s = upload_stream_new(c, &ss, &map, name, length, p);
2731 pa_proplist_free(p);
2733 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
2735 reply = reply_new(tag);
2736 pa_tagstruct_putu32(reply, s->index);
2737 pa_tagstruct_putu32(reply, length);
2738 pa_pstream_send_tagstruct(c->pstream, reply);
2741 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2742 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2747 pa_native_connection_assert_ref(c);
2750 if (pa_tagstruct_getu32(t, &channel) < 0 ||
2751 !pa_tagstruct_eof(t)) {
2756 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2758 s = pa_idxset_get_by_index(c->output_streams, channel);
2759 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2760 CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2762 if (!s->memchunk.memblock)
2763 pa_pstream_send_error(c->pstream, tag, PA_ERR_TOOLARGE);
2764 else if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
2765 pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
2767 pa_pstream_send_simple_ack(c->pstream, tag);
2769 upload_stream_unlink(s);
2772 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2773 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2774 uint32_t sink_index;
2777 const char *name, *sink_name;
2780 pa_tagstruct *reply;
2782 pa_native_connection_assert_ref(c);
2785 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2787 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
2788 pa_tagstruct_gets(t, &sink_name) < 0 ||
2789 pa_tagstruct_getu32(t, &volume) < 0 ||
2790 pa_tagstruct_gets(t, &name) < 0) {
2795 CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
2796 CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
2797 CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2798 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2800 if (sink_index != PA_INVALID_INDEX)
2801 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
2803 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK);
2805 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
2807 p = pa_proplist_new();
2809 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2810 !pa_tagstruct_eof(t)) {
2812 pa_proplist_free(p);
2816 pa_proplist_update(p, PA_UPDATE_MERGE, c->client->proplist);
2818 if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
2819 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2820 pa_proplist_free(p);
2824 pa_proplist_free(p);
2826 reply = reply_new(tag);
2828 if (c->version >= 13)
2829 pa_tagstruct_putu32(reply, idx);
2831 pa_pstream_send_tagstruct(c->pstream, reply);
2834 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2835 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2838 pa_native_connection_assert_ref(c);
2841 if (pa_tagstruct_gets(t, &name) < 0 ||
2842 !pa_tagstruct_eof(t)) {
2847 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2848 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2850 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
2851 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2855 pa_pstream_send_simple_ack(c->pstream, tag);
2858 static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
2861 pa_assert(original);
2865 if (c->version < 12) {
2866 /* Before protocol version 12 we didn't support S32 samples,
2867 * so we need to lie about this to the client */
2869 if (fixed->format == PA_SAMPLE_S32LE)
2870 fixed->format = PA_SAMPLE_FLOAT32LE;
2871 if (fixed->format == PA_SAMPLE_S32BE)
2872 fixed->format = PA_SAMPLE_FLOAT32BE;
2875 if (c->version < 15) {
2876 if (fixed->format == PA_SAMPLE_S24LE || fixed->format == PA_SAMPLE_S24_32LE)
2877 fixed->format = PA_SAMPLE_FLOAT32LE;
2878 if (fixed->format == PA_SAMPLE_S24BE || fixed->format == PA_SAMPLE_S24_32BE)
2879 fixed->format = PA_SAMPLE_FLOAT32BE;
2883 static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) {
2884 pa_sample_spec fixed_ss;
2887 pa_sink_assert_ref(sink);
2889 fixup_sample_spec(c, &fixed_ss, &sink->sample_spec);
2893 PA_TAG_U32, sink->index,
2894 PA_TAG_STRING, sink->name,
2895 PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2896 PA_TAG_SAMPLE_SPEC, &fixed_ss,
2897 PA_TAG_CHANNEL_MAP, &sink->channel_map,
2898 PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
2899 PA_TAG_CVOLUME, pa_sink_get_volume(sink, FALSE),
2900 PA_TAG_BOOLEAN, pa_sink_get_mute(sink, FALSE),
2901 PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
2902 PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
2903 PA_TAG_USEC, pa_sink_get_latency(sink),
2904 PA_TAG_STRING, sink->driver,
2905 PA_TAG_U32, sink->flags,
2908 if (c->version >= 13) {
2909 pa_tagstruct_put_proplist(t, sink->proplist);
2910 pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
2913 if (c->version >= 15) {
2914 pa_tagstruct_put_volume(t, sink->base_volume);
2915 if (PA_UNLIKELY(pa_sink_get_state(sink) == PA_SINK_INVALID_STATE))
2916 pa_log_error("Internal sink state is invalid.");
2917 pa_tagstruct_putu32(t, pa_sink_get_state(sink));
2918 pa_tagstruct_putu32(t, sink->n_volume_steps);
2919 pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX);
2922 if (c->version >= 16) {
2923 pa_tagstruct_putu32(t, sink->ports ? pa_hashmap_size(sink->ports) : 0);
2929 PA_HASHMAP_FOREACH(p, sink->ports, state) {
2930 pa_tagstruct_puts(t, p->name);
2931 pa_tagstruct_puts(t, p->description);
2932 pa_tagstruct_putu32(t, p->priority);
2936 pa_tagstruct_puts(t, sink->active_port ? sink->active_port->name : NULL);
2940 static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
2941 pa_sample_spec fixed_ss;
2944 pa_source_assert_ref(source);
2946 fixup_sample_spec(c, &fixed_ss, &source->sample_spec);
2950 PA_TAG_U32, source->index,
2951 PA_TAG_STRING, source->name,
2952 PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2953 PA_TAG_SAMPLE_SPEC, &fixed_ss,
2954 PA_TAG_CHANNEL_MAP, &source->channel_map,
2955 PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
2956 PA_TAG_CVOLUME, pa_source_get_volume(source, FALSE),
2957 PA_TAG_BOOLEAN, pa_source_get_mute(source, FALSE),
2958 PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
2959 PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
2960 PA_TAG_USEC, pa_source_get_latency(source),
2961 PA_TAG_STRING, source->driver,
2962 PA_TAG_U32, source->flags,
2965 if (c->version >= 13) {
2966 pa_tagstruct_put_proplist(t, source->proplist);
2967 pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
2970 if (c->version >= 15) {
2971 pa_tagstruct_put_volume(t, source->base_volume);
2972 if (PA_UNLIKELY(pa_source_get_state(source) == PA_SOURCE_INVALID_STATE))
2973 pa_log_error("Internal source state is invalid.");
2974 pa_tagstruct_putu32(t, pa_source_get_state(source));
2975 pa_tagstruct_putu32(t, source->n_volume_steps);
2976 pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX);
2979 if (c->version >= 16) {
2981 pa_tagstruct_putu32(t, source->ports ? pa_hashmap_size(source->ports) : 0);
2983 if (source->ports) {
2987 PA_HASHMAP_FOREACH(p, source->ports, state) {
2988 pa_tagstruct_puts(t, p->name);
2989 pa_tagstruct_puts(t, p->description);
2990 pa_tagstruct_putu32(t, p->priority);
2994 pa_tagstruct_puts(t, source->active_port ? source->active_port->name : NULL);
2998 static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
3002 pa_tagstruct_putu32(t, client->index);
3003 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
3004 pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
3005 pa_tagstruct_puts(t, client->driver);
3007 if (c->version >= 13)
3008 pa_tagstruct_put_proplist(t, client->proplist);
3011 static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
3018 pa_tagstruct_putu32(t, card->index);
3019 pa_tagstruct_puts(t, card->name);
3020 pa_tagstruct_putu32(t, card->module ? card->module->index : PA_INVALID_INDEX);
3021 pa_tagstruct_puts(t, card->driver);
3023 pa_tagstruct_putu32(t, card->profiles ? pa_hashmap_size(card->profiles) : 0);
3025 if (card->profiles) {
3026 while ((p = pa_hashmap_iterate(card->profiles, &state, NULL))) {
3027 pa_tagstruct_puts(t, p->name);
3028 pa_tagstruct_puts(t, p->description);
3029 pa_tagstruct_putu32(t, p->n_sinks);
3030 pa_tagstruct_putu32(t, p->n_sources);
3031 pa_tagstruct_putu32(t, p->priority);
3035 pa_tagstruct_puts(t, card->active_profile ? card->active_profile->name : NULL);
3036 pa_tagstruct_put_proplist(t, card->proplist);
3039 static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module) {
3043 pa_tagstruct_putu32(t, module->index);
3044 pa_tagstruct_puts(t, module->name);
3045 pa_tagstruct_puts(t, module->argument);
3046 pa_tagstruct_putu32(t, (uint32_t) pa_module_get_n_used(module));
3048 if (c->version < 15)
3049 pa_tagstruct_put_boolean(t, FALSE); /* autoload is obsolete */
3051 if (c->version >= 15)
3052 pa_tagstruct_put_proplist(t, module->proplist);
3055 static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) {
3056 pa_sample_spec fixed_ss;
3057 pa_usec_t sink_latency;
3061 pa_sink_input_assert_ref(s);
3063 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3065 pa_tagstruct_putu32(t, s->index);
3066 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3067 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3068 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3069 pa_tagstruct_putu32(t, s->sink->index);
3070 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3071 pa_tagstruct_put_channel_map(t, &s->channel_map);
3072 pa_tagstruct_put_cvolume(t, pa_sink_input_get_volume(s, &v, TRUE));
3073 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
3074 pa_tagstruct_put_usec(t, sink_latency);
3075 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
3076 pa_tagstruct_puts(t, s->driver);
3077 if (c->version >= 11)
3078 pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
3079 if (c->version >= 13)
3080 pa_tagstruct_put_proplist(t, s->proplist);
3081 if (c->version >= 19)
3082 pa_tagstruct_put_boolean(t, (pa_sink_input_get_state(s) == PA_SINK_INPUT_CORKED));
3085 static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
3086 pa_sample_spec fixed_ss;
3087 pa_usec_t source_latency;
3090 pa_source_output_assert_ref(s);
3092 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3094 pa_tagstruct_putu32(t, s->index);
3095 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3096 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3097 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3098 pa_tagstruct_putu32(t, s->source->index);
3099 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3100 pa_tagstruct_put_channel_map(t, &s->channel_map);
3101 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s, &source_latency));
3102 pa_tagstruct_put_usec(t, source_latency);
3103 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
3104 pa_tagstruct_puts(t, s->driver);
3105 if (c->version >= 13)
3106 pa_tagstruct_put_proplist(t, s->proplist);
3107 if (c->version >= 19)
3108 pa_tagstruct_put_boolean(t, (pa_source_output_get_state(s) == PA_SOURCE_OUTPUT_CORKED));
3111 static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {
3112 pa_sample_spec fixed_ss;
3118 if (e->memchunk.memblock)
3119 fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
3121 memset(&fixed_ss, 0, sizeof(fixed_ss));
3123 pa_tagstruct_putu32(t, e->index);
3124 pa_tagstruct_puts(t, e->name);
3126 if (e->volume_is_set)
3129 pa_cvolume_init(&v);
3131 pa_tagstruct_put_cvolume(t, &v);
3132 pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0);
3133 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3134 pa_tagstruct_put_channel_map(t, &e->channel_map);
3135 pa_tagstruct_putu32(t, (uint32_t) e->memchunk.length);
3136 pa_tagstruct_put_boolean(t, e->lazy);
3137 pa_tagstruct_puts(t, e->filename);
3139 if (c->version >= 13)
3140 pa_tagstruct_put_proplist(t, e->proplist);
3143 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3144 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3146 pa_sink *sink = NULL;
3147 pa_source *source = NULL;
3148 pa_client *client = NULL;
3149 pa_card *card = NULL;
3150 pa_module *module = NULL;
3151 pa_sink_input *si = NULL;
3152 pa_source_output *so = NULL;
3153 pa_scache_entry *sce = NULL;
3154 const char *name = NULL;
3155 pa_tagstruct *reply;
3157 pa_native_connection_assert_ref(c);
3160 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3161 (command != PA_COMMAND_GET_CLIENT_INFO &&
3162 command != PA_COMMAND_GET_MODULE_INFO &&
3163 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
3164 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
3165 pa_tagstruct_gets(t, &name) < 0) ||
3166 !pa_tagstruct_eof(t)) {
3171 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3172 CHECK_VALIDITY(c->pstream, !name ||
3173 (command == PA_COMMAND_GET_SINK_INFO &&
3174 pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SINK)) ||
3175 (command == PA_COMMAND_GET_SOURCE_INFO &&
3176 pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SOURCE)) ||
3177 pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3178 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3179 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3180 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3182 if (command == PA_COMMAND_GET_SINK_INFO) {
3183 if (idx != PA_INVALID_INDEX)
3184 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3186 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3187 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
3188 if (idx != PA_INVALID_INDEX)
3189 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3191 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3192 } else if (command == PA_COMMAND_GET_CARD_INFO) {
3193 if (idx != PA_INVALID_INDEX)
3194 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
3196 card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
3197 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
3198 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3199 else if (command == PA_COMMAND_GET_MODULE_INFO)
3200 module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3201 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
3202 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3203 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
3204 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3206 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
3207 if (idx != PA_INVALID_INDEX)
3208 sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
3210 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
3213 if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
3214 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3218 reply = reply_new(tag);
3220 sink_fill_tagstruct(c, reply, sink);
3222 source_fill_tagstruct(c, reply, source);
3224 client_fill_tagstruct(c, reply, client);
3226 card_fill_tagstruct(c, reply, card);
3228 module_fill_tagstruct(c, reply, module);
3230 sink_input_fill_tagstruct(c, reply, si);
3232 source_output_fill_tagstruct(c, reply, so);
3234 scache_fill_tagstruct(c, reply, sce);
3235 pa_pstream_send_tagstruct(c->pstream, reply);
3238 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3239 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3243 pa_tagstruct *reply;
3245 pa_native_connection_assert_ref(c);
3248 if (!pa_tagstruct_eof(t)) {
3253 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3255 reply = reply_new(tag);
3257 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3258 i = c->protocol->core->sinks;
3259 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3260 i = c->protocol->core->sources;
3261 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3262 i = c->protocol->core->clients;
3263 else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3264 i = c->protocol->core->cards;
3265 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3266 i = c->protocol->core->modules;
3267 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3268 i = c->protocol->core->sink_inputs;
3269 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3270 i = c->protocol->core->source_outputs;
3272 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3273 i = c->protocol->core->scache;
3277 for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
3278 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3279 sink_fill_tagstruct(c, reply, p);
3280 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3281 source_fill_tagstruct(c, reply, p);
3282 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3283 client_fill_tagstruct(c, reply, p);
3284 else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3285 card_fill_tagstruct(c, reply, p);
3286 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3287 module_fill_tagstruct(c, reply, p);
3288 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3289 sink_input_fill_tagstruct(c, reply, p);
3290 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3291 source_output_fill_tagstruct(c, reply, p);
3293 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3294 scache_fill_tagstruct(c, reply, p);
3299 pa_pstream_send_tagstruct(c->pstream, reply);
3302 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3303 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3304 pa_tagstruct *reply;
3306 pa_source *def_source;
3307 pa_sample_spec fixed_ss;
3310 pa_native_connection_assert_ref(c);
3313 if (!pa_tagstruct_eof(t)) {
3318 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3320 reply = reply_new(tag);
3321 pa_tagstruct_puts(reply, PACKAGE_NAME);
3322 pa_tagstruct_puts(reply, PACKAGE_VERSION);
3324 u = pa_get_user_name_malloc();
3325 pa_tagstruct_puts(reply, u);
3328 h = pa_get_host_name_malloc();
3329 pa_tagstruct_puts(reply, h);
3332 fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
3333 pa_tagstruct_put_sample_spec(reply, &fixed_ss);
3335 def_sink = pa_namereg_get_default_sink(c->protocol->core);
3336 pa_tagstruct_puts(reply, def_sink ? def_sink->name : NULL);
3337 def_source = pa_namereg_get_default_source(c->protocol->core);
3338 pa_tagstruct_puts(reply, def_source ? def_source->name : NULL);
3340 pa_tagstruct_putu32(reply, c->protocol->core->cookie);
3342 if (c->version >= 15)
3343 pa_tagstruct_put_channel_map(reply, &c->protocol->core->default_channel_map);
3345 pa_pstream_send_tagstruct(c->pstream, reply);
3348 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
3350 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3352 pa_native_connection_assert_ref(c);
3354 t = pa_tagstruct_new(NULL, 0);
3355 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
3356 pa_tagstruct_putu32(t, (uint32_t) -1);
3357 pa_tagstruct_putu32(t, e);
3358 pa_tagstruct_putu32(t, idx);
3359 pa_pstream_send_tagstruct(c->pstream, t);
3362 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3363 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3364 pa_subscription_mask_t m;
3366 pa_native_connection_assert_ref(c);
3369 if (pa_tagstruct_getu32(t, &m) < 0 ||
3370 !pa_tagstruct_eof(t)) {
3375 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3376 CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
3378 if (c->subscription)
3379 pa_subscription_free(c->subscription);
3382 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
3383 pa_assert(c->subscription);
3385 c->subscription = NULL;
3387 pa_pstream_send_simple_ack(c->pstream, tag);
3390 static void command_set_volume(
3397 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3400 pa_sink *sink = NULL;
3401 pa_source *source = NULL;
3402 pa_sink_input *si = NULL;
3403 const char *name = NULL;
3404 const char *client_name;
3406 pa_native_connection_assert_ref(c);
3409 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3410 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3411 (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3412 pa_tagstruct_get_cvolume(t, &volume) ||
3413 !pa_tagstruct_eof(t)) {
3418 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3419 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_VOLUME ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
3420 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3421 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3422 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3423 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
3427 case PA_COMMAND_SET_SINK_VOLUME:
3428 if (idx != PA_INVALID_INDEX)
3429 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3431 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3434 case PA_COMMAND_SET_SOURCE_VOLUME:
3435 if (idx != PA_INVALID_INDEX)
3436 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3438 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3441 case PA_COMMAND_SET_SINK_INPUT_VOLUME:
3442 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3446 pa_assert_not_reached();
3449 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3451 client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3454 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &sink->sample_spec), tag, PA_ERR_INVALID);
3456 pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
3457 pa_sink_set_volume(sink, &volume, TRUE, TRUE);
3458 } else if (source) {
3459 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &source->sample_spec), tag, PA_ERR_INVALID);
3461 pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
3462 pa_source_set_volume(source, &volume, TRUE);
3464 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &si->sample_spec), tag, PA_ERR_INVALID);
3466 pa_log_debug("Client %s changes volume of sink input %s.",
3468 pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3469 pa_sink_input_set_volume(si, &volume, TRUE, TRUE);
3472 pa_pstream_send_simple_ack(c->pstream, tag);
3475 static void command_set_mute(
3482 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3485 pa_sink *sink = NULL;
3486 pa_source *source = NULL;
3487 pa_sink_input *si = NULL;
3488 const char *name = NULL, *client_name;
3490 pa_native_connection_assert_ref(c);
3493 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3494 (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3495 (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3496 pa_tagstruct_get_boolean(t, &mute) ||
3497 !pa_tagstruct_eof(t)) {
3502 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3503 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_MUTE ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
3504 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3505 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3506 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3510 case PA_COMMAND_SET_SINK_MUTE:
3511 if (idx != PA_INVALID_INDEX)
3512 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3514 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3518 case PA_COMMAND_SET_SOURCE_MUTE:
3519 if (idx != PA_INVALID_INDEX)
3520 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3522 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3526 case PA_COMMAND_SET_SINK_INPUT_MUTE:
3527 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3531 pa_assert_not_reached();
3534 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3536 client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3539 pa_log_debug("Client %s changes mute of sink %s.", client_name, sink->name);
3540 pa_sink_set_mute(sink, mute, TRUE);
3541 } else if (source) {
3542 pa_log_debug("Client %s changes mute of source %s.", client_name, source->name);
3543 pa_source_set_mute(source, mute, TRUE);
3545 pa_log_debug("Client %s changes mute of sink input %s.",
3547 pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3548 pa_sink_input_set_mute(si, mute, TRUE);
3551 pa_pstream_send_simple_ack(c->pstream, tag);
3554 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3555 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3560 pa_native_connection_assert_ref(c);
3563 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3564 pa_tagstruct_get_boolean(t, &b) < 0 ||
3565 !pa_tagstruct_eof(t)) {
3570 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3571 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3572 s = pa_idxset_get_by_index(c->output_streams, idx);
3573 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3574 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3576 pa_sink_input_cork(s->sink_input, b);
3579 s->is_underrun = TRUE;
3581 pa_pstream_send_simple_ack(c->pstream, tag);
3584 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3585 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3589 pa_native_connection_assert_ref(c);
3592 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3593 !pa_tagstruct_eof(t)) {
3598 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3599 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3600 s = pa_idxset_get_by_index(c->output_streams, idx);
3601 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3602 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3605 case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
3606 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
3609 case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
3610 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
3613 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
3614 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
3618 pa_assert_not_reached();
3621 pa_pstream_send_simple_ack(c->pstream, tag);
3624 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3625 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3630 pa_native_connection_assert_ref(c);
3633 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3634 pa_tagstruct_get_boolean(t, &b) < 0 ||
3635 !pa_tagstruct_eof(t)) {
3640 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3641 s = pa_idxset_get_by_index(c->record_streams, idx);
3642 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3644 pa_source_output_cork(s->source_output, b);
3645 pa_memblockq_prebuf_force(s->memblockq);
3646 pa_pstream_send_simple_ack(c->pstream, tag);
3649 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3650 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3654 pa_native_connection_assert_ref(c);
3657 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3658 !pa_tagstruct_eof(t)) {
3663 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3664 s = pa_idxset_get_by_index(c->record_streams, idx);
3665 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3667 pa_memblockq_flush_read(s->memblockq);
3668 pa_pstream_send_simple_ack(c->pstream, tag);
3671 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3672 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3675 pa_tagstruct *reply;
3677 pa_native_connection_assert_ref(c);
3680 memset(&a, 0, sizeof(a));
3682 if (pa_tagstruct_getu32(t, &idx) < 0) {
3687 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3689 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
3691 pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3693 s = pa_idxset_get_by_index(c->output_streams, idx);
3694 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3695 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3697 if (pa_tagstruct_get(
3699 PA_TAG_U32, &a.maxlength,
3700 PA_TAG_U32, &a.tlength,
3701 PA_TAG_U32, &a.prebuf,
3702 PA_TAG_U32, &a.minreq,
3703 PA_TAG_INVALID) < 0 ||
3704 (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3705 (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3706 !pa_tagstruct_eof(t)) {
3711 s->adjust_latency = adjust_latency;
3712 s->early_requests = early_requests;
3715 fix_playback_buffer_attr(s);
3716 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);
3718 reply = reply_new(tag);
3719 pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3720 pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
3721 pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
3722 pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
3724 if (c->version >= 13)
3725 pa_tagstruct_put_usec(reply, s->configured_sink_latency);
3729 pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3730 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
3732 s = pa_idxset_get_by_index(c->record_streams, idx);
3733 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3735 if (pa_tagstruct_get(
3737 PA_TAG_U32, &a.maxlength,
3738 PA_TAG_U32, &a.fragsize,
3739 PA_TAG_INVALID) < 0 ||
3740 (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3741 (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3742 !pa_tagstruct_eof(t)) {
3747 s->adjust_latency = adjust_latency;
3748 s->early_requests = early_requests;
3751 fix_record_buffer_attr_pre(s);
3752 pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
3753 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
3754 fix_record_buffer_attr_post(s);
3756 reply = reply_new(tag);
3757 pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3758 pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
3760 if (c->version >= 13)
3761 pa_tagstruct_put_usec(reply, s->configured_source_latency);
3764 pa_pstream_send_tagstruct(c->pstream, reply);
3767 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3768 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3772 pa_native_connection_assert_ref(c);
3775 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3776 pa_tagstruct_getu32(t, &rate) < 0 ||
3777 !pa_tagstruct_eof(t)) {
3782 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3783 CHECK_VALIDITY(c->pstream, rate > 0 && rate <= PA_RATE_MAX, tag, PA_ERR_INVALID);
3785 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
3788 s = pa_idxset_get_by_index(c->output_streams, idx);
3789 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3790 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3792 pa_sink_input_set_rate(s->sink_input, rate);
3796 pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
3798 s = pa_idxset_get_by_index(c->record_streams, idx);
3799 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3801 pa_source_output_set_rate(s->source_output, rate);
3804 pa_pstream_send_simple_ack(c->pstream, tag);
3807 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3808 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3813 pa_native_connection_assert_ref(c);
3816 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3818 p = pa_proplist_new();
3820 if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
3822 if (pa_tagstruct_getu32(t, &mode) < 0 ||
3823 pa_tagstruct_get_proplist(t, p) < 0 ||
3824 !pa_tagstruct_eof(t)) {
3826 pa_proplist_free(p);
3832 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3833 pa_tagstruct_getu32(t, &mode) < 0 ||
3834 pa_tagstruct_get_proplist(t, p) < 0 ||
3835 !pa_tagstruct_eof(t)) {
3837 pa_proplist_free(p);
3842 if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) {
3843 pa_proplist_free(p);
3844 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
3847 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
3850 s = pa_idxset_get_by_index(c->output_streams, idx);
3851 if (!s || !playback_stream_isinstance(s)) {
3852 pa_proplist_free(p);
3853 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3855 pa_sink_input_update_proplist(s->sink_input, mode, p);
3857 } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
3860 if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
3861 pa_proplist_free(p);
3862 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3864 pa_source_output_update_proplist(s->source_output, mode, p);
3867 pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
3869 pa_client_update_proplist(c->client, mode, p);
3872 pa_pstream_send_simple_ack(c->pstream, tag);
3873 pa_proplist_free(p);
3876 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3877 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3879 unsigned changed = 0;
3881 pa_strlist *l = NULL;
3883 pa_native_connection_assert_ref(c);
3886 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3888 if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
3890 if (pa_tagstruct_getu32(t, &idx) < 0) {
3896 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3899 s = pa_idxset_get_by_index(c->output_streams, idx);
3900 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3901 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3903 p = s->sink_input->proplist;
3905 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3908 s = pa_idxset_get_by_index(c->record_streams, idx);
3909 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3911 p = s->source_output->proplist;
3913 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3915 p = c->client->proplist;
3921 if (pa_tagstruct_gets(t, &k) < 0) {
3930 l = pa_strlist_prepend(l, k);
3933 if (!pa_tagstruct_eof(t)) {
3942 l = pa_strlist_pop(l, &z);
3947 changed += (unsigned) (pa_proplist_unset(p, z) >= 0);
3951 pa_pstream_send_simple_ack(c->pstream, tag);
3954 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3957 s = pa_idxset_get_by_index(c->output_streams, idx);
3958 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
3960 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3963 s = pa_idxset_get_by_index(c->record_streams, idx);
3964 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
3967 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3968 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
3973 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3974 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3977 pa_native_connection_assert_ref(c);
3980 if (pa_tagstruct_gets(t, &s) < 0 ||
3981 !pa_tagstruct_eof(t)) {
3986 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3987 CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID);
3989 if (command == PA_COMMAND_SET_DEFAULT_SOURCE) {
3992 source = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SOURCE);
3993 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
3995 pa_namereg_set_default_source(c->protocol->core, source);
3998 pa_assert(command == PA_COMMAND_SET_DEFAULT_SINK);
4000 sink = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SINK);
4001 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4003 pa_namereg_set_default_sink(c->protocol->core, sink);
4006 pa_pstream_send_simple_ack(c->pstream, tag);
4009 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4010 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4014 pa_native_connection_assert_ref(c);
4017 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4018 pa_tagstruct_gets(t, &name) < 0 ||
4019 !pa_tagstruct_eof(t)) {
4024 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4025 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
4027 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
4030 s = pa_idxset_get_by_index(c->output_streams, idx);
4031 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4032 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4034 pa_sink_input_set_name(s->sink_input, name);
4038 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
4040 s = pa_idxset_get_by_index(c->record_streams, idx);
4041 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4043 pa_source_output_set_name(s->source_output, name);
4046 pa_pstream_send_simple_ack(c->pstream, tag);
4049 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4050 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4053 pa_native_connection_assert_ref(c);
4056 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4057 !pa_tagstruct_eof(t)) {
4062 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4064 if (command == PA_COMMAND_KILL_CLIENT) {
4067 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
4068 CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
4070 pa_native_connection_ref(c);
4071 pa_client_kill(client);
4073 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
4076 s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4077 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4079 pa_native_connection_ref(c);
4080 pa_sink_input_kill(s);
4082 pa_source_output *s;
4084 pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
4086 s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4087 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4089 pa_native_connection_ref(c);
4090 pa_source_output_kill(s);
4093 pa_pstream_send_simple_ack(c->pstream, tag);
4094 pa_native_connection_unref(c);
4097 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4098 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4100 const char *name, *argument;
4101 pa_tagstruct *reply;
4103 pa_native_connection_assert_ref(c);
4106 if (pa_tagstruct_gets(t, &name) < 0 ||
4107 pa_tagstruct_gets(t, &argument) < 0 ||
4108 !pa_tagstruct_eof(t)) {
4113 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4114 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
4115 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
4117 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
4118 pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
4122 reply = reply_new(tag);
4123 pa_tagstruct_putu32(reply, m->index);
4124 pa_pstream_send_tagstruct(c->pstream, reply);
4127 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4128 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4132 pa_native_connection_assert_ref(c);
4135 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4136 !pa_tagstruct_eof(t)) {
4141 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4142 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4143 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
4145 pa_module_unload_request(m, FALSE);
4146 pa_pstream_send_simple_ack(c->pstream, tag);
4149 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4150 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4151 uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
4152 const char *name_device = NULL;
4154 pa_native_connection_assert_ref(c);
4157 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4158 pa_tagstruct_getu32(t, &idx_device) < 0 ||
4159 pa_tagstruct_gets(t, &name_device) < 0 ||
4160 !pa_tagstruct_eof(t)) {
4165 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4166 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4168 CHECK_VALIDITY(c->pstream, !name_device || pa_namereg_is_valid_name_or_wildcard(name_device, command == PA_COMMAND_MOVE_SINK_INPUT ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
4169 CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || name_device, tag, PA_ERR_INVALID);
4170 CHECK_VALIDITY(c->pstream, idx_device == PA_INVALID_INDEX || !name_device, tag, PA_ERR_INVALID);
4171 CHECK_VALIDITY(c->pstream, !name_device || idx_device == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4173 if (command == PA_COMMAND_MOVE_SINK_INPUT) {
4174 pa_sink_input *si = NULL;
4175 pa_sink *sink = NULL;
4177 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4179 if (idx_device != PA_INVALID_INDEX)
4180 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
4182 sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK);
4184 CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
4186 if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
4187 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4191 pa_source_output *so = NULL;
4194 pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
4196 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4198 if (idx_device != PA_INVALID_INDEX)
4199 source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
4201 source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE);
4203 CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
4205 if (pa_source_output_move_to(so, source, TRUE) < 0) {
4206 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4211 pa_pstream_send_simple_ack(c->pstream, tag);
4214 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4215 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4216 uint32_t idx = PA_INVALID_INDEX;
4217 const char *name = NULL;
4220 pa_native_connection_assert_ref(c);
4223 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4224 pa_tagstruct_gets(t, &name) < 0 ||
4225 pa_tagstruct_get_boolean(t, &b) < 0 ||
4226 !pa_tagstruct_eof(t)) {
4231 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4232 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SUSPEND_SINK ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE) || *name == 0, tag, PA_ERR_INVALID);
4233 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4234 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4235 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4237 if (command == PA_COMMAND_SUSPEND_SINK) {
4239 if (idx == PA_INVALID_INDEX && name && !*name) {
4241 pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
4243 if (pa_sink_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4244 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4248 pa_sink *sink = NULL;
4250 if (idx != PA_INVALID_INDEX)
4251 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4253 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4255 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4257 if (pa_sink_suspend(sink, b, PA_SUSPEND_USER) < 0) {
4258 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4264 pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
4266 if (idx == PA_INVALID_INDEX && name && !*name) {
4268 pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
4270 if (pa_source_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4271 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4278 if (idx != PA_INVALID_INDEX)
4279 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4281 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4283 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4285 if (pa_source_suspend(source, b, PA_SUSPEND_USER) < 0) {
4286 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4292 pa_pstream_send_simple_ack(c->pstream, tag);
4295 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4296 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4297 uint32_t idx = PA_INVALID_INDEX;
4298 const char *name = NULL;
4300 pa_native_protocol_ext_cb_t cb;
4302 pa_native_connection_assert_ref(c);
4305 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4306 pa_tagstruct_gets(t, &name) < 0) {
4311 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4312 CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
4313 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4314 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4315 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4317 if (idx != PA_INVALID_INDEX)
4318 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4320 for (m = pa_idxset_first(c->protocol->core->modules, &idx); m; m = pa_idxset_next(c->protocol->core->modules, &idx))
4321 if (strcmp(name, m->name) == 0)
4325 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
4326 CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4328 cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m);
4329 CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION);
4331 if (cb(c->protocol, m, c, tag, t) < 0)
4335 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4336 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4337 uint32_t idx = PA_INVALID_INDEX;
4338 const char *name = NULL, *profile = NULL;
4339 pa_card *card = NULL;
4342 pa_native_connection_assert_ref(c);
4345 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4346 pa_tagstruct_gets(t, &name) < 0 ||
4347 pa_tagstruct_gets(t, &profile) < 0 ||
4348 !pa_tagstruct_eof(t)) {
4353 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4354 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4355 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4356 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4357 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4359 if (idx != PA_INVALID_INDEX)
4360 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4362 card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
4364 CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4366 if ((ret = pa_card_set_profile(card, profile, TRUE)) < 0) {
4367 pa_pstream_send_error(c->pstream, tag, -ret);
4371 pa_pstream_send_simple_ack(c->pstream, tag);
4374 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4375 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4376 uint32_t idx = PA_INVALID_INDEX;
4377 const char *name = NULL, *port = NULL;
4380 pa_native_connection_assert_ref(c);
4383 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4384 pa_tagstruct_gets(t, &name) < 0 ||
4385 pa_tagstruct_gets(t, &port) < 0 ||
4386 !pa_tagstruct_eof(t)) {
4391 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4392 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name_or_wildcard(name, command == PA_COMMAND_SET_SINK_PORT ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
4393 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4394 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4395 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4397 if (command == PA_COMMAND_SET_SINK_PORT) {
4400 if (idx != PA_INVALID_INDEX)
4401 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4403 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4405 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4407 if ((ret = pa_sink_set_port(sink, port, TRUE)) < 0) {
4408 pa_pstream_send_error(c->pstream, tag, -ret);
4414 pa_assert(command = PA_COMMAND_SET_SOURCE_PORT);
4416 if (idx != PA_INVALID_INDEX)
4417 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4419 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4421 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4423 if ((ret = pa_source_set_port(source, port, TRUE)) < 0) {
4424 pa_pstream_send_error(c->pstream, tag, -ret);
4429 pa_pstream_send_simple_ack(c->pstream, tag);
4432 /*** pstream callbacks ***/
4434 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
4435 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4439 pa_native_connection_assert_ref(c);
4441 if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
4442 pa_log("invalid packet.");
4443 native_connection_unlink(c);
4447 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) {
4448 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4449 output_stream *stream;
4453 pa_native_connection_assert_ref(c);
4455 if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
4456 pa_log_debug("Client sent block for invalid stream.");
4461 /* pa_log("got %lu bytes", (unsigned long) chunk->length); */
4463 if (playback_stream_isinstance(stream)) {
4464 playback_stream *ps = PLAYBACK_STREAM(stream);
4466 pa_atomic_inc(&ps->seek_or_post_in_queue);
4467 if (chunk->memblock) {
4468 if (seek != PA_SEEK_RELATIVE || offset != 0)
4469 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, chunk, NULL);
4471 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
4473 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);
4476 upload_stream *u = UPLOAD_STREAM(stream);
4479 if (!u->memchunk.memblock) {
4480 if (u->length == chunk->length && chunk->memblock) {
4481 u->memchunk = *chunk;
4482 pa_memblock_ref(u->memchunk.memblock);
4485 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
4486 u->memchunk.index = u->memchunk.length = 0;
4490 pa_assert(u->memchunk.memblock);
4493 if (l > chunk->length)
4498 dst = pa_memblock_acquire(u->memchunk.memblock);
4500 if (chunk->memblock) {
4502 src = pa_memblock_acquire(chunk->memblock);
4504 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
4505 (uint8_t*) src + chunk->index, l);
4507 pa_memblock_release(chunk->memblock);
4509 pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec);
4511 pa_memblock_release(u->memchunk.memblock);
4513 u->memchunk.length += l;
4519 static void pstream_die_callback(pa_pstream *p, void *userdata) {
4520 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4523 pa_native_connection_assert_ref(c);
4525 native_connection_unlink(c);
4526 pa_log_info("Connection died.");
4529 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
4530 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4533 pa_native_connection_assert_ref(c);
4535 native_connection_send_memblock(c);
4538 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4541 if (!(q = pa_thread_mq_get()))
4542 pa_pstream_send_revoke(p, block_id);
4544 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4547 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4550 if (!(q = pa_thread_mq_get()))
4551 pa_pstream_send_release(p, block_id);
4553 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4556 /*** client callbacks ***/
4558 static void client_kill_cb(pa_client *c) {
4561 native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
4562 pa_log_info("Connection killed.");
4565 static void client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl) {
4567 pa_native_connection *c;
4570 c = PA_NATIVE_CONNECTION(client->userdata);
4571 pa_native_connection_assert_ref(c);
4573 if (c->version < 15)
4576 t = pa_tagstruct_new(NULL, 0);
4577 pa_tagstruct_putu32(t, PA_COMMAND_CLIENT_EVENT);
4578 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
4579 pa_tagstruct_puts(t, event);
4580 pa_tagstruct_put_proplist(t, pl);
4581 pa_pstream_send_tagstruct(c->pstream, t);
4584 /*** module entry points ***/
4586 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) {
4587 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4590 pa_native_connection_assert_ref(c);
4591 pa_assert(c->auth_timeout_event == e);
4593 if (!c->authorized) {
4594 native_connection_unlink(c);
4595 pa_log_info("Connection terminated due to authentication timeout.");
4599 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
4600 pa_native_connection *c;
4603 pa_client_new_data data;
4609 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
4610 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
4611 pa_iochannel_free(io);
4615 pa_client_new_data_init(&data);
4616 data.module = o->module;
4617 data.driver = __FILE__;
4618 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
4619 pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname);
4620 pa_proplist_sets(data.proplist, "native-protocol.peer", pname);
4621 client = pa_client_new(p->core, &data);
4622 pa_client_new_data_done(&data);
4627 c = pa_msgobject_new(pa_native_connection);
4628 c->parent.parent.free = native_connection_free;
4629 c->parent.process_msg = native_connection_process_msg;
4631 c->options = pa_native_options_ref(o);
4632 c->authorized = FALSE;
4634 if (o->auth_anonymous) {
4635 pa_log_info("Client authenticated anonymously.");
4636 c->authorized = TRUE;
4639 if (!c->authorized &&
4641 pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
4643 pa_log_info("Client authenticated by IP ACL.");
4644 c->authorized = TRUE;
4648 c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
4650 c->auth_timeout_event = NULL;
4652 c->is_local = pa_iochannel_socket_is_local(io);
4656 c->client->kill = client_kill_cb;
4657 c->client->send_event = client_send_event_cb;
4658 c->client->userdata = c;
4660 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
4661 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
4662 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
4663 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
4664 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
4665 pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
4666 pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
4668 c->pdispatch = pa_pdispatch_new(p->core->mainloop, TRUE, command_table, PA_COMMAND_MAX);
4670 c->record_streams = pa_idxset_new(NULL, NULL);
4671 c->output_streams = pa_idxset_new(NULL, NULL);
4673 c->rrobin_index = PA_IDXSET_INVALID;
4674 c->subscription = NULL;
4676 pa_idxset_put(p->connections, c, NULL);
4679 if (pa_iochannel_creds_supported(io))
4680 pa_iochannel_creds_enable(io);
4683 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
4686 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
4687 pa_native_connection *c;
4693 while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
4694 if (c->options->module == m)
4695 native_connection_unlink(c);
4698 static pa_native_protocol* native_protocol_new(pa_core *c) {
4699 pa_native_protocol *p;
4704 p = pa_xnew(pa_native_protocol, 1);
4707 p->connections = pa_idxset_new(NULL, NULL);
4711 p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
4713 for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4714 pa_hook_init(&p->hooks[h], p);
4716 pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
4721 pa_native_protocol* pa_native_protocol_get(pa_core *c) {
4722 pa_native_protocol *p;
4724 if ((p = pa_shared_get(c, "native-protocol")))
4725 return pa_native_protocol_ref(p);
4727 return native_protocol_new(c);
4730 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
4732 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4739 void pa_native_protocol_unref(pa_native_protocol *p) {
4740 pa_native_connection *c;
4744 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4746 if (PA_REFCNT_DEC(p) > 0)
4749 while ((c = pa_idxset_first(p->connections, NULL)))
4750 native_connection_unlink(c);
4752 pa_idxset_free(p->connections, NULL, NULL);
4754 pa_strlist_free(p->servers);
4756 for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4757 pa_hook_done(&p->hooks[h]);
4759 pa_hashmap_free(p->extensions, NULL, NULL);
4761 pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
4766 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name) {
4768 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4771 p->servers = pa_strlist_prepend(p->servers, name);
4773 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4776 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
4778 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4781 p->servers = pa_strlist_remove(p->servers, name);
4783 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4786 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
4788 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4793 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
4795 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4800 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb) {
4802 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4805 pa_assert(!pa_hashmap_get(p->extensions, m));
4807 pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) (unsigned long) cb) == 0);
4811 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
4813 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4816 pa_assert_se(pa_hashmap_remove(p->extensions, m));
4819 pa_native_options* pa_native_options_new(void) {
4820 pa_native_options *o;
4822 o = pa_xnew0(pa_native_options, 1);
4828 pa_native_options* pa_native_options_ref(pa_native_options *o) {
4830 pa_assert(PA_REFCNT_VALUE(o) >= 1);
4837 void pa_native_options_unref(pa_native_options *o) {
4839 pa_assert(PA_REFCNT_VALUE(o) >= 1);
4841 if (PA_REFCNT_DEC(o) > 0)
4844 pa_xfree(o->auth_group);
4847 pa_ip_acl_free(o->auth_ip_acl);
4850 pa_auth_cookie_unref(o->auth_cookie);
4855 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
4860 pa_assert(PA_REFCNT_VALUE(o) >= 1);
4863 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
4864 pa_log("auth-anonymous= expects a boolean argument.");
4869 if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &enabled) < 0) {
4870 pa_log("auth-group-enabled= expects a boolean argument.");
4874 pa_xfree(o->auth_group);
4875 o->auth_group = enabled ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
4879 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4882 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
4885 if (!(ipa = pa_ip_acl_new(acl))) {
4886 pa_log("Failed to parse IP ACL '%s'", acl);
4891 pa_ip_acl_free(o->auth_ip_acl);
4893 o->auth_ip_acl = ipa;
4897 if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
4898 pa_log("auth-cookie-enabled= expects a boolean argument.");
4903 pa_auth_cookie_unref(o->auth_cookie);
4908 /* The new name for this is 'auth-cookie', for compat reasons
4909 * we check the old name too */
4910 if (!(cn = pa_modargs_get_value(ma, "auth-cookie", NULL)))
4911 if (!(cn = pa_modargs_get_value(ma, "cookie", NULL)))
4912 cn = PA_NATIVE_COOKIE_FILE;
4914 if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, PA_NATIVE_COOKIE_LENGTH)))
4918 o->auth_cookie = NULL;
4923 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
4924 pa_native_connection_assert_ref(c);
4929 pa_client* pa_native_connection_get_client(pa_native_connection *c) {
4930 pa_native_connection_assert_ref(c);