]> code.delx.au - pulseaudio/blob - src/pulsecore/protocol-native.c
protocol-native: Early request bandaid for high latency sink/source
[pulseaudio] / src / pulsecore / protocol-native.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31
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>
38 #include <pulse/internal.h>
39
40 #include <pulsecore/native-common.h>
41 #include <pulsecore/packet.h>
42 #include <pulsecore/client.h>
43 #include <pulsecore/source-output.h>
44 #include <pulsecore/sink-input.h>
45 #include <pulsecore/pstream.h>
46 #include <pulsecore/tagstruct.h>
47 #include <pulsecore/pdispatch.h>
48 #include <pulsecore/pstream-util.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/creds.h>
57 #include <pulsecore/core-util.h>
58 #include <pulsecore/ipacl.h>
59 #include <pulsecore/thread-mq.h>
60
61 #include "protocol-native.h"
62
63 /* #define PROTOCOL_NATIVE_DEBUG */
64
65 /* Kick a client if it doesn't authenticate within this time */
66 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
67
68 /* Don't accept more connection than this */
69 #define MAX_CONNECTIONS 64
70
71 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
72 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
73 #define DEFAULT_PROCESS_MSEC 20 /* 20ms */
74 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
75
76 struct pa_native_protocol;
77
78 typedef struct record_stream {
79 pa_msgobject parent;
80
81 pa_native_connection *connection;
82 uint32_t index;
83
84 pa_source_output *source_output;
85 pa_memblockq *memblockq;
86
87 bool adjust_latency:1;
88 bool early_requests:1;
89
90 /* Requested buffer attributes */
91 pa_buffer_attr buffer_attr_req;
92 /* Fixed-up and adjusted buffer attributes */
93 pa_buffer_attr buffer_attr;
94
95 pa_atomic_t on_the_fly;
96 pa_usec_t configured_source_latency;
97 size_t drop_initial;
98
99 /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
100 size_t on_the_fly_snapshot;
101 pa_usec_t current_monitor_latency;
102 pa_usec_t current_source_latency;
103 } record_stream;
104
105 #define RECORD_STREAM(o) (record_stream_cast(o))
106 PA_DEFINE_PRIVATE_CLASS(record_stream, pa_msgobject);
107
108 typedef struct output_stream {
109 pa_msgobject parent;
110 } output_stream;
111
112 #define OUTPUT_STREAM(o) (output_stream_cast(o))
113 PA_DEFINE_PRIVATE_CLASS(output_stream, pa_msgobject);
114
115 typedef struct playback_stream {
116 output_stream parent;
117
118 pa_native_connection *connection;
119 uint32_t index;
120
121 pa_sink_input *sink_input;
122 pa_memblockq *memblockq;
123
124 bool adjust_latency:1;
125 bool early_requests:1;
126
127 bool is_underrun:1;
128 bool drain_request:1;
129 uint32_t drain_tag;
130 uint32_t syncid;
131
132 /* Optimization to avoid too many rewinds with a lot of small blocks */
133 pa_atomic_t seek_or_post_in_queue;
134 int64_t seek_windex;
135
136 pa_atomic_t missing;
137 pa_usec_t configured_sink_latency;
138 /* Requested buffer attributes */
139 pa_buffer_attr buffer_attr_req;
140 /* Fixed-up and adjusted buffer attributes */
141 pa_buffer_attr buffer_attr;
142
143 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
144 int64_t read_index, write_index;
145 size_t render_memblockq_length;
146 pa_usec_t current_sink_latency;
147 uint64_t playing_for, underrun_for;
148 } playback_stream;
149
150 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
151 PA_DEFINE_PRIVATE_CLASS(playback_stream, output_stream);
152
153 typedef struct upload_stream {
154 output_stream parent;
155
156 pa_native_connection *connection;
157 uint32_t index;
158
159 pa_memchunk memchunk;
160 size_t length;
161 char *name;
162 pa_sample_spec sample_spec;
163 pa_channel_map channel_map;
164 pa_proplist *proplist;
165 } upload_stream;
166
167 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
168 PA_DEFINE_PRIVATE_CLASS(upload_stream, output_stream);
169
170 struct pa_native_connection {
171 pa_msgobject parent;
172 pa_native_protocol *protocol;
173 pa_native_options *options;
174 bool authorized:1;
175 bool is_local:1;
176 uint32_t version;
177 pa_client *client;
178 pa_pstream *pstream;
179 pa_pdispatch *pdispatch;
180 pa_idxset *record_streams, *output_streams;
181 uint32_t rrobin_index;
182 pa_subscription *subscription;
183 pa_time_event *auth_timeout_event;
184 };
185
186 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
187 PA_DEFINE_PRIVATE_CLASS(pa_native_connection, pa_msgobject);
188
189 struct pa_native_protocol {
190 PA_REFCNT_DECLARE;
191
192 pa_core *core;
193 pa_idxset *connections;
194
195 pa_strlist *servers;
196 pa_hook hooks[PA_NATIVE_HOOK_MAX];
197
198 pa_hashmap *extensions;
199 };
200
201 enum {
202 SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY = PA_SOURCE_OUTPUT_MESSAGE_MAX
203 };
204
205 enum {
206 SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
207 SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */
208 SINK_INPUT_MESSAGE_FLUSH,
209 SINK_INPUT_MESSAGE_TRIGGER,
210 SINK_INPUT_MESSAGE_SEEK,
211 SINK_INPUT_MESSAGE_PREBUF_FORCE,
212 SINK_INPUT_MESSAGE_UPDATE_LATENCY,
213 SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
214 };
215
216 enum {
217 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, /* data requested from sink input from the main loop */
218 PLAYBACK_STREAM_MESSAGE_UNDERFLOW,
219 PLAYBACK_STREAM_MESSAGE_OVERFLOW,
220 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK,
221 PLAYBACK_STREAM_MESSAGE_STARTED,
222 PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
223 };
224
225 enum {
226 RECORD_STREAM_MESSAGE_POST_DATA /* data from source output to main loop */
227 };
228
229 enum {
230 CONNECTION_MESSAGE_RELEASE,
231 CONNECTION_MESSAGE_REVOKE
232 };
233
234 static bool sink_input_process_underrun_cb(pa_sink_input *i);
235 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
236 static void sink_input_kill_cb(pa_sink_input *i);
237 static void sink_input_suspend_cb(pa_sink_input *i, bool suspend);
238 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest);
239 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
240 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
241 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes);
242 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl);
243
244 static void native_connection_send_memblock(pa_native_connection *c);
245 static void playback_stream_request_bytes(struct playback_stream*s);
246
247 static void source_output_kill_cb(pa_source_output *o);
248 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
249 static void source_output_suspend_cb(pa_source_output *o, bool suspend);
250 static void source_output_moving_cb(pa_source_output *o, pa_source *dest);
251 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
252 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl);
253
254 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
255 static int source_output_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
256
257 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
258 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
259 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
260 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
261 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
262 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
263 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
264 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
265 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
266 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
267 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
268 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
269 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
270 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
271 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
272 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
273 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
274 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
275 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
276 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
277 static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
278 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
279 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
280 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
281 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
282 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
283 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
284 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
285 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
286 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
287 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
288 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
289 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
290 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
291 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
292 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
293 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
294 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
295 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
296 static void command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
297
298 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
299 [PA_COMMAND_ERROR] = NULL,
300 [PA_COMMAND_TIMEOUT] = NULL,
301 [PA_COMMAND_REPLY] = NULL,
302 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
303 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
304 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
305 [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
306 [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
307 [PA_COMMAND_AUTH] = command_auth,
308 [PA_COMMAND_REQUEST] = NULL,
309 [PA_COMMAND_EXIT] = command_exit,
310 [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
311 [PA_COMMAND_LOOKUP_SINK] = command_lookup,
312 [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
313 [PA_COMMAND_STAT] = command_stat,
314 [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
315 [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
316 [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
317 [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
318 [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
319 [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
320 [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
321 [PA_COMMAND_GET_SINK_INFO] = command_get_info,
322 [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
323 [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
324 [PA_COMMAND_GET_CARD_INFO] = command_get_info,
325 [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
326 [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
327 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
328 [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
329 [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
330 [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
331 [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
332 [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
333 [PA_COMMAND_GET_CARD_INFO_LIST] = command_get_info_list,
334 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
335 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
336 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
337 [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
338 [PA_COMMAND_SUBSCRIBE] = command_subscribe,
339
340 [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
341 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
342 [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
343 [PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME] = command_set_volume,
344
345 [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
346 [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
347 [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
348 [PA_COMMAND_SET_SOURCE_OUTPUT_MUTE] = command_set_mute,
349
350 [PA_COMMAND_SUSPEND_SINK] = command_suspend,
351 [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
352
353 [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
354 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
355 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
356 [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
357
358 [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
359 [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
360
361 [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
362 [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
363 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
364 [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
365 [PA_COMMAND_KILL_CLIENT] = command_kill,
366 [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
367 [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
368 [PA_COMMAND_LOAD_MODULE] = command_load_module,
369 [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
370
371 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE] = NULL,
372 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE] = NULL,
373 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE] = NULL,
374 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE] = NULL,
375
376 [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
377 [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream,
378
379 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
380 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
381
382 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
383 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
384
385 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = command_update_proplist,
386 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = command_update_proplist,
387 [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = command_update_proplist,
388
389 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = command_remove_proplist,
390 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
391 [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
392
393 [PA_COMMAND_SET_CARD_PROFILE] = command_set_card_profile,
394
395 [PA_COMMAND_SET_SINK_PORT] = command_set_sink_or_source_port,
396 [PA_COMMAND_SET_SOURCE_PORT] = command_set_sink_or_source_port,
397
398 [PA_COMMAND_SET_PORT_LATENCY_OFFSET] = command_set_port_latency_offset,
399
400 [PA_COMMAND_EXTENSION] = command_extension
401 };
402
403 /* structure management */
404
405 /* Called from main context */
406 static void upload_stream_unlink(upload_stream *s) {
407 pa_assert(s);
408
409 if (!s->connection)
410 return;
411
412 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
413 s->connection = NULL;
414 upload_stream_unref(s);
415 }
416
417 /* Called from main context */
418 static void upload_stream_free(pa_object *o) {
419 upload_stream *s = UPLOAD_STREAM(o);
420 pa_assert(s);
421
422 upload_stream_unlink(s);
423
424 pa_xfree(s->name);
425
426 if (s->proplist)
427 pa_proplist_free(s->proplist);
428
429 if (s->memchunk.memblock)
430 pa_memblock_unref(s->memchunk.memblock);
431
432 pa_xfree(s);
433 }
434
435 /* Called from main context */
436 static upload_stream* upload_stream_new(
437 pa_native_connection *c,
438 const pa_sample_spec *ss,
439 const pa_channel_map *map,
440 const char *name,
441 size_t length,
442 pa_proplist *p) {
443
444 upload_stream *s;
445
446 pa_assert(c);
447 pa_assert(ss);
448 pa_assert(name);
449 pa_assert(length > 0);
450 pa_assert(p);
451
452 s = pa_msgobject_new(upload_stream);
453 s->parent.parent.parent.free = upload_stream_free;
454 s->connection = c;
455 s->sample_spec = *ss;
456 s->channel_map = *map;
457 s->name = pa_xstrdup(name);
458 pa_memchunk_reset(&s->memchunk);
459 s->length = length;
460 s->proplist = pa_proplist_copy(p);
461 pa_proplist_update(s->proplist, PA_UPDATE_MERGE, c->client->proplist);
462
463 pa_idxset_put(c->output_streams, s, &s->index);
464
465 return s;
466 }
467
468 /* Called from main context */
469 static void record_stream_unlink(record_stream *s) {
470 pa_assert(s);
471
472 if (!s->connection)
473 return;
474
475 if (s->source_output) {
476 pa_source_output_unlink(s->source_output);
477 pa_source_output_unref(s->source_output);
478 s->source_output = NULL;
479 }
480
481 pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
482 s->connection = NULL;
483 record_stream_unref(s);
484 }
485
486 /* Called from main context */
487 static void record_stream_free(pa_object *o) {
488 record_stream *s = RECORD_STREAM(o);
489 pa_assert(s);
490
491 record_stream_unlink(s);
492
493 pa_memblockq_free(s->memblockq);
494 pa_xfree(s);
495 }
496
497 /* Called from main context */
498 static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
499 record_stream *s = RECORD_STREAM(o);
500 record_stream_assert_ref(s);
501
502 if (!s->connection)
503 return -1;
504
505 switch (code) {
506
507 case RECORD_STREAM_MESSAGE_POST_DATA:
508
509 /* We try to keep up to date with how many bytes are
510 * currently on the fly */
511 pa_atomic_sub(&s->on_the_fly, chunk->length);
512
513 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
514 /* pa_log_warn("Failed to push data into output queue."); */
515 return -1;
516 }
517
518 if (!pa_pstream_is_pending(s->connection->pstream))
519 native_connection_send_memblock(s->connection);
520
521 break;
522 }
523
524 return 0;
525 }
526
527 /* Called from main context */
528 static void fix_record_buffer_attr_pre(record_stream *s) {
529
530 size_t frame_size;
531 pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec;
532
533 pa_assert(s);
534
535 /* This function will be called from the main thread, before as
536 * well as after the source output has been activated using
537 * pa_source_output_put()! That means it may not touch any
538 * ->thread_info data! */
539
540 frame_size = pa_frame_size(&s->source_output->sample_spec);
541 s->buffer_attr = s->buffer_attr_req;
542
543 if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
544 s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
545 if (s->buffer_attr.maxlength <= 0)
546 s->buffer_attr.maxlength = (uint32_t) frame_size;
547
548 if (s->buffer_attr.fragsize == (uint32_t) -1)
549 s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
550 if (s->buffer_attr.fragsize <= 0)
551 s->buffer_attr.fragsize = (uint32_t) frame_size;
552
553 orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(s->buffer_attr.fragsize, &s->source_output->sample_spec);
554
555 if (s->early_requests) {
556
557 /* In early request mode we need to emulate the classic
558 * fragment-based playback model. Unfortunately we have no
559 * mechanism to tell the source how often we want it to send us
560 * data. The next best thing we can do is to set the source's
561 * total buffer (i.e. its latency) to the fragment size. That
562 * way it will have to send data at least that often. */
563
564 source_usec = fragsize_usec;
565
566 } else if (s->adjust_latency) {
567
568 /* So, the user asked us to adjust the latency according to
569 * what the source can provide. Half the latency will be
570 * spent on the hw buffer, half of it in the async buffer
571 * queue we maintain for each client. */
572
573 source_usec = fragsize_usec/2;
574
575 } else {
576
577 /* Ok, the user didn't ask us to adjust the latency, hence we
578 * don't */
579
580 source_usec = (pa_usec_t) -1;
581 }
582
583 if (source_usec != (pa_usec_t) -1)
584 s->configured_source_latency = pa_source_output_set_requested_latency(s->source_output, source_usec);
585 else
586 s->configured_source_latency = 0;
587
588 if (s->early_requests) {
589
590 /* Ok, we didn't necessarily get what we were asking for. We
591 * might still get the proper fragment interval, we just can't
592 * guarantee it. */
593
594 if (fragsize_usec != s->configured_source_latency)
595 pa_log_debug("Could not configure a sufficiently low latency. Early requests might not be satisifed.");
596
597 } else if (s->adjust_latency) {
598
599 /* Now subtract what we actually got */
600
601 if (fragsize_usec >= s->configured_source_latency*2)
602 fragsize_usec -= s->configured_source_latency;
603 else
604 fragsize_usec = s->configured_source_latency;
605 }
606
607 if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) !=
608 pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec))
609
610 s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
611
612 if (s->buffer_attr.fragsize <= 0)
613 s->buffer_attr.fragsize = (uint32_t) frame_size;
614 }
615
616 /* Called from main context */
617 static void fix_record_buffer_attr_post(record_stream *s) {
618 size_t base;
619
620 pa_assert(s);
621
622 /* This function will be called from the main thread, before as
623 * well as after the source output has been activated using
624 * pa_source_output_put()! That means it may not touch and
625 * ->thread_info data! */
626
627 base = pa_frame_size(&s->source_output->sample_spec);
628
629 s->buffer_attr.fragsize = (s->buffer_attr.fragsize/base)*base;
630 if (s->buffer_attr.fragsize <= 0)
631 s->buffer_attr.fragsize = base;
632
633 if (s->buffer_attr.fragsize > s->buffer_attr.maxlength)
634 s->buffer_attr.fragsize = s->buffer_attr.maxlength;
635 }
636
637 /* Called from main context */
638 static record_stream* record_stream_new(
639 pa_native_connection *c,
640 pa_source *source,
641 pa_sample_spec *ss,
642 pa_channel_map *map,
643 pa_idxset *formats,
644 pa_buffer_attr *attr,
645 pa_cvolume *volume,
646 bool muted,
647 bool muted_set,
648 pa_source_output_flags_t flags,
649 pa_proplist *p,
650 bool adjust_latency,
651 bool early_requests,
652 bool relative_volume,
653 bool peak_detect,
654 pa_sink_input *direct_on_input,
655 int *ret) {
656
657 record_stream *s;
658 pa_source_output *source_output = NULL;
659 pa_source_output_new_data data;
660 char *memblockq_name;
661
662 pa_assert(c);
663 pa_assert(ss);
664 pa_assert(p);
665 pa_assert(ret);
666
667 pa_source_output_new_data_init(&data);
668
669 pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
670 data.driver = __FILE__;
671 data.module = c->options->module;
672 data.client = c->client;
673 if (source)
674 pa_source_output_new_data_set_source(&data, source, false);
675 if (pa_sample_spec_valid(ss))
676 pa_source_output_new_data_set_sample_spec(&data, ss);
677 if (pa_channel_map_valid(map))
678 pa_source_output_new_data_set_channel_map(&data, map);
679 if (formats)
680 pa_source_output_new_data_set_formats(&data, formats);
681 data.direct_on_input = direct_on_input;
682 if (volume) {
683 pa_source_output_new_data_set_volume(&data, volume);
684 data.volume_is_absolute = !relative_volume;
685 data.save_volume = false;
686 }
687 if (muted_set) {
688 pa_source_output_new_data_set_muted(&data, muted);
689 data.save_muted = false;
690 }
691 if (peak_detect)
692 data.resample_method = PA_RESAMPLER_PEAKS;
693 data.flags = flags;
694
695 *ret = -pa_source_output_new(&source_output, c->protocol->core, &data);
696
697 pa_source_output_new_data_done(&data);
698
699 if (!source_output)
700 return NULL;
701
702 s = pa_msgobject_new(record_stream);
703 s->parent.parent.free = record_stream_free;
704 s->parent.process_msg = record_stream_process_msg;
705 s->connection = c;
706 s->source_output = source_output;
707 s->buffer_attr_req = *attr;
708 s->adjust_latency = adjust_latency;
709 s->early_requests = early_requests;
710 pa_atomic_store(&s->on_the_fly, 0);
711
712 s->source_output->parent.process_msg = source_output_process_msg;
713 s->source_output->push = source_output_push_cb;
714 s->source_output->kill = source_output_kill_cb;
715 s->source_output->get_latency = source_output_get_latency_cb;
716 s->source_output->moving = source_output_moving_cb;
717 s->source_output->suspend = source_output_suspend_cb;
718 s->source_output->send_event = source_output_send_event_cb;
719 s->source_output->userdata = s;
720
721 fix_record_buffer_attr_pre(s);
722
723 memblockq_name = pa_sprintf_malloc("native protocol record stream memblockq [%u]", s->source_output->index);
724 s->memblockq = pa_memblockq_new(
725 memblockq_name,
726 0,
727 s->buffer_attr.maxlength,
728 0,
729 &source_output->sample_spec,
730 1,
731 0,
732 0,
733 NULL);
734 pa_xfree(memblockq_name);
735
736 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
737 fix_record_buffer_attr_post(s);
738
739 *ss = s->source_output->sample_spec;
740 *map = s->source_output->channel_map;
741
742 pa_idxset_put(c->record_streams, s, &s->index);
743
744 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
745 ((double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) + (double) s->configured_source_latency) / PA_USEC_PER_MSEC,
746 (double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) / PA_USEC_PER_MSEC,
747 (double) s->configured_source_latency / PA_USEC_PER_MSEC);
748
749 pa_source_output_put(s->source_output);
750 return s;
751 }
752
753 /* Called from main context */
754 static void record_stream_send_killed(record_stream *r) {
755 pa_tagstruct *t;
756 record_stream_assert_ref(r);
757
758 t = pa_tagstruct_new(NULL, 0);
759 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
760 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
761 pa_tagstruct_putu32(t, r->index);
762 pa_pstream_send_tagstruct(r->connection->pstream, t);
763 }
764
765 /* Called from main context */
766 static void playback_stream_unlink(playback_stream *s) {
767 pa_assert(s);
768
769 if (!s->connection)
770 return;
771
772 if (s->sink_input) {
773 pa_sink_input_unlink(s->sink_input);
774 pa_sink_input_unref(s->sink_input);
775 s->sink_input = NULL;
776 }
777
778 if (s->drain_request)
779 pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
780
781 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
782 s->connection = NULL;
783 playback_stream_unref(s);
784 }
785
786 /* Called from main context */
787 static void playback_stream_free(pa_object* o) {
788 playback_stream *s = PLAYBACK_STREAM(o);
789 pa_assert(s);
790
791 playback_stream_unlink(s);
792
793 pa_memblockq_free(s->memblockq);
794 pa_xfree(s);
795 }
796
797 /* Called from main context */
798 static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
799 playback_stream *s = PLAYBACK_STREAM(o);
800 playback_stream_assert_ref(s);
801
802 if (!s->connection)
803 return -1;
804
805 switch (code) {
806
807 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
808 pa_tagstruct *t;
809 int l = 0;
810
811 for (;;) {
812 if ((l = pa_atomic_load(&s->missing)) <= 0)
813 return 0;
814
815 if (pa_atomic_cmpxchg(&s->missing, l, 0))
816 break;
817 }
818
819 t = pa_tagstruct_new(NULL, 0);
820 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
821 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
822 pa_tagstruct_putu32(t, s->index);
823 pa_tagstruct_putu32(t, (uint32_t) l);
824 pa_pstream_send_tagstruct(s->connection->pstream, t);
825
826 #ifdef PROTOCOL_NATIVE_DEBUG
827 pa_log("Requesting %lu bytes", (unsigned long) l);
828 #endif
829 break;
830 }
831
832 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
833 pa_tagstruct *t;
834
835 #ifdef PROTOCOL_NATIVE_DEBUG
836 pa_log("signalling underflow");
837 #endif
838
839 /* Report that we're empty */
840 t = pa_tagstruct_new(NULL, 0);
841 pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
842 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
843 pa_tagstruct_putu32(t, s->index);
844 if (s->connection->version >= 23)
845 pa_tagstruct_puts64(t, offset);
846 pa_pstream_send_tagstruct(s->connection->pstream, t);
847 break;
848 }
849
850 case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
851 pa_tagstruct *t;
852
853 /* Notify the user we're overflowed*/
854 t = pa_tagstruct_new(NULL, 0);
855 pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
856 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
857 pa_tagstruct_putu32(t, s->index);
858 pa_pstream_send_tagstruct(s->connection->pstream, t);
859 break;
860 }
861
862 case PLAYBACK_STREAM_MESSAGE_STARTED:
863
864 if (s->connection->version >= 13) {
865 pa_tagstruct *t;
866
867 /* Notify the user we started playback */
868 t = pa_tagstruct_new(NULL, 0);
869 pa_tagstruct_putu32(t, PA_COMMAND_STARTED);
870 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
871 pa_tagstruct_putu32(t, s->index);
872 pa_pstream_send_tagstruct(s->connection->pstream, t);
873 }
874
875 break;
876
877 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
878 pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
879 break;
880
881 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH:
882
883 s->buffer_attr.tlength = (uint32_t) offset;
884
885 if (s->connection->version >= 15) {
886 pa_tagstruct *t;
887
888 t = pa_tagstruct_new(NULL, 0);
889 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
890 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
891 pa_tagstruct_putu32(t, s->index);
892 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
893 pa_tagstruct_putu32(t, s->buffer_attr.tlength);
894 pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
895 pa_tagstruct_putu32(t, s->buffer_attr.minreq);
896 pa_tagstruct_put_usec(t, s->configured_sink_latency);
897 pa_pstream_send_tagstruct(s->connection->pstream, t);
898 }
899
900 break;
901 }
902
903 return 0;
904 }
905
906 /* Called from main context */
907 static void fix_playback_buffer_attr(playback_stream *s) {
908 size_t frame_size, max_prebuf;
909 pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec;
910
911 pa_assert(s);
912
913 #ifdef PROTOCOL_NATIVE_DEBUG
914 pa_log("Client requested: maxlength=%li bytes tlength=%li bytes minreq=%li bytes prebuf=%li bytes",
915 (long) s->buffer_attr_req.maxlength,
916 (long) s->buffer_attr_req.tlength,
917 (long) s->buffer_attr_req.minreq,
918 (long) s->buffer_attr_req.prebuf);
919
920 pa_log("Client requested: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
921 (unsigned long) (pa_bytes_to_usec(s->buffer_attr_req.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
922 (unsigned long) (pa_bytes_to_usec(s->buffer_attr_req.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
923 (unsigned long) (pa_bytes_to_usec(s->buffer_attr_req.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
924 (unsigned long) (pa_bytes_to_usec(s->buffer_attr_req.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC));
925 #endif
926
927 /* This function will be called from the main thread, before as
928 * well as after the sink input has been activated using
929 * pa_sink_input_put()! That means it may not touch any
930 * ->thread_info data, such as the memblockq! */
931
932 frame_size = pa_frame_size(&s->sink_input->sample_spec);
933 s->buffer_attr = s->buffer_attr_req;
934
935 if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
936 s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
937 if (s->buffer_attr.maxlength <= 0)
938 s->buffer_attr.maxlength = (uint32_t) frame_size;
939
940 if (s->buffer_attr.tlength == (uint32_t) -1)
941 s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
942 if (s->buffer_attr.tlength <= 0)
943 s->buffer_attr.tlength = (uint32_t) frame_size;
944 if (s->buffer_attr.tlength > s->buffer_attr.maxlength)
945 s->buffer_attr.tlength = s->buffer_attr.maxlength;
946
947 if (s->buffer_attr.minreq == (uint32_t) -1) {
948 uint32_t process = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
949 /* With low-latency, tlength/4 gives a decent default in all of traditional, adjust latency and early request modes. */
950 uint32_t m = s->buffer_attr.tlength / 4;
951 if (frame_size)
952 m -= m % frame_size;
953 s->buffer_attr.minreq = PA_MIN(process, m);
954 }
955 if (s->buffer_attr.minreq <= 0)
956 s->buffer_attr.minreq = (uint32_t) frame_size;
957
958 if (s->buffer_attr.tlength < s->buffer_attr.minreq+frame_size)
959 s->buffer_attr.tlength = s->buffer_attr.minreq+(uint32_t) frame_size;
960
961 orig_tlength_usec = tlength_usec = pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec);
962 orig_minreq_usec = minreq_usec = pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec);
963
964 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
965 (double) tlength_usec / PA_USEC_PER_MSEC,
966 (double) minreq_usec / PA_USEC_PER_MSEC);
967
968 if (s->early_requests) {
969
970 /* In early request mode we need to emulate the classic
971 * fragment-based playback model. Unfortunately we have no
972 * mechanism to tell the sink how often we want to be queried
973 * for data. The next best thing we can do is to set the sink's
974 * total buffer (i.e. its latency) to the fragment size. That
975 * way it will have to query us at least that often. */
976
977 sink_usec = minreq_usec;
978 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
979
980 } else if (s->adjust_latency) {
981
982 /* So, the user asked us to adjust the latency of the stream
983 * buffer according to the what the sink can provide. The
984 * tlength passed in shall be the overall latency. Roughly
985 * half the latency will be spent on the hw buffer, the other
986 * half of it in the async buffer queue we maintain for each
987 * client. In between we'll have a safety space of size
988 * 2*minreq. Why the 2*minreq? When the hw buffer is completely
989 * empty and needs to be filled, then our buffer must have
990 * enough data to fulfill this request immediately and thus
991 * have at least the same tlength as the size of the hw
992 * buffer. It additionally needs space for 2 times minreq
993 * because if the buffer ran empty and a partial fillup
994 * happens immediately on the next iteration we need to be
995 * able to fulfill it and give the application also minreq
996 * time to fill it up again for the next request Makes 2 times
997 * minreq in plus.. */
998
999 if (tlength_usec > minreq_usec*2)
1000 sink_usec = (tlength_usec - minreq_usec*2)/2;
1001 else
1002 sink_usec = 0;
1003
1004 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
1005
1006 } else {
1007
1008 /* Ok, the user didn't ask us to adjust the latency, but we
1009 * still need to make sure that the parameters from the user
1010 * do make sense. */
1011
1012 if (tlength_usec > minreq_usec*2)
1013 sink_usec = (tlength_usec - minreq_usec*2);
1014 else
1015 sink_usec = 0;
1016
1017 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
1018 }
1019
1020 s->configured_sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
1021
1022 if (s->early_requests) {
1023
1024 /* Ok, we didn't necessarily get what we were asking for. We
1025 * might still get the proper fragment interval, we just can't
1026 * guarantee it. */
1027
1028 if (minreq_usec != s->configured_sink_latency)
1029 pa_log_debug("Could not configure a sufficiently low latency. Early requests might not be satisifed.");
1030
1031 } else if (s->adjust_latency) {
1032
1033 /* Ok, we didn't necessarily get what we were asking for, so
1034 * let's subtract from what we asked for for the remaining
1035 * buffer space */
1036
1037 if (tlength_usec >= s->configured_sink_latency)
1038 tlength_usec -= s->configured_sink_latency;
1039 }
1040
1041 pa_log_debug("Requested latency=%0.2f ms, Received latency=%0.2f ms",
1042 (double) sink_usec / PA_USEC_PER_MSEC,
1043 (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
1044
1045 /* FIXME: This is actually larger than necessary, since not all of
1046 * the sink latency is actually rewritable. */
1047 if (tlength_usec < s->configured_sink_latency + 2*minreq_usec)
1048 tlength_usec = s->configured_sink_latency + 2*minreq_usec;
1049
1050 if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) !=
1051 pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec))
1052 s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec);
1053
1054 if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) !=
1055 pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec))
1056 s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
1057
1058 if (s->buffer_attr.minreq <= 0) {
1059 s->buffer_attr.minreq = (uint32_t) frame_size;
1060 s->buffer_attr.tlength += (uint32_t) frame_size*2;
1061 }
1062
1063 if (s->buffer_attr.tlength <= s->buffer_attr.minreq)
1064 s->buffer_attr.tlength = s->buffer_attr.minreq*2 + (uint32_t) frame_size;
1065
1066 max_prebuf = s->buffer_attr.tlength + (uint32_t)frame_size - s->buffer_attr.minreq;
1067
1068 if (s->buffer_attr.prebuf == (uint32_t) -1 ||
1069 s->buffer_attr.prebuf > max_prebuf)
1070 s->buffer_attr.prebuf = max_prebuf;
1071
1072 #ifdef PROTOCOL_NATIVE_DEBUG
1073 pa_log("Client accepted: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
1074 (unsigned long) (pa_bytes_to_usec(s->buffer_attr.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
1075 (unsigned long) (pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
1076 (unsigned long) (pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC),
1077 (unsigned long) (pa_bytes_to_usec(s->buffer_attr.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC));
1078 #endif
1079 }
1080
1081 /* Called from main context */
1082 static playback_stream* playback_stream_new(
1083 pa_native_connection *c,
1084 pa_sink *sink,
1085 pa_sample_spec *ss,
1086 pa_channel_map *map,
1087 pa_idxset *formats,
1088 pa_buffer_attr *a,
1089 pa_cvolume *volume,
1090 bool muted,
1091 bool muted_set,
1092 pa_sink_input_flags_t flags,
1093 pa_proplist *p,
1094 bool adjust_latency,
1095 bool early_requests,
1096 bool relative_volume,
1097 uint32_t syncid,
1098 uint32_t *missing,
1099 int *ret) {
1100
1101 /* Note: This function takes ownership of the 'formats' param, so we need
1102 * to take extra care to not leak it */
1103
1104 playback_stream *ssync;
1105 playback_stream *s = NULL;
1106 pa_sink_input *sink_input = NULL;
1107 pa_memchunk silence;
1108 uint32_t idx;
1109 int64_t start_index;
1110 pa_sink_input_new_data data;
1111 char *memblockq_name;
1112
1113 pa_assert(c);
1114 pa_assert(ss);
1115 pa_assert(missing);
1116 pa_assert(p);
1117 pa_assert(ret);
1118
1119 /* Find syncid group */
1120 PA_IDXSET_FOREACH(ssync, c->output_streams, idx) {
1121
1122 if (!playback_stream_isinstance(ssync))
1123 continue;
1124
1125 if (ssync->syncid == syncid)
1126 break;
1127 }
1128
1129 /* Synced streams must connect to the same sink */
1130 if (ssync) {
1131
1132 if (!sink)
1133 sink = ssync->sink_input->sink;
1134 else if (sink != ssync->sink_input->sink) {
1135 *ret = PA_ERR_INVALID;
1136 goto out;
1137 }
1138 }
1139
1140 pa_sink_input_new_data_init(&data);
1141
1142 pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
1143 data.driver = __FILE__;
1144 data.module = c->options->module;
1145 data.client = c->client;
1146 if (sink)
1147 pa_sink_input_new_data_set_sink(&data, sink, false);
1148 if (pa_sample_spec_valid(ss))
1149 pa_sink_input_new_data_set_sample_spec(&data, ss);
1150 if (pa_channel_map_valid(map))
1151 pa_sink_input_new_data_set_channel_map(&data, map);
1152 if (formats) {
1153 pa_sink_input_new_data_set_formats(&data, formats);
1154 /* Ownership transferred to new_data, so we don't free it ourselves */
1155 formats = NULL;
1156 }
1157 if (volume) {
1158 pa_sink_input_new_data_set_volume(&data, volume);
1159 data.volume_is_absolute = !relative_volume;
1160 data.save_volume = false;
1161 }
1162 if (muted_set) {
1163 pa_sink_input_new_data_set_muted(&data, muted);
1164 data.save_muted = false;
1165 }
1166 data.sync_base = ssync ? ssync->sink_input : NULL;
1167 data.flags = flags;
1168
1169 *ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data);
1170
1171 pa_sink_input_new_data_done(&data);
1172
1173 if (!sink_input)
1174 goto out;
1175
1176 s = pa_msgobject_new(playback_stream);
1177 s->parent.parent.parent.free = playback_stream_free;
1178 s->parent.parent.process_msg = playback_stream_process_msg;
1179 s->connection = c;
1180 s->syncid = syncid;
1181 s->sink_input = sink_input;
1182 s->is_underrun = true;
1183 s->drain_request = false;
1184 pa_atomic_store(&s->missing, 0);
1185 s->buffer_attr_req = *a;
1186 s->adjust_latency = adjust_latency;
1187 s->early_requests = early_requests;
1188 pa_atomic_store(&s->seek_or_post_in_queue, 0);
1189 s->seek_windex = -1;
1190
1191 s->sink_input->parent.process_msg = sink_input_process_msg;
1192 s->sink_input->pop = sink_input_pop_cb;
1193 s->sink_input->process_underrun = sink_input_process_underrun_cb;
1194 s->sink_input->process_rewind = sink_input_process_rewind_cb;
1195 s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1196 s->sink_input->update_max_request = sink_input_update_max_request_cb;
1197 s->sink_input->kill = sink_input_kill_cb;
1198 s->sink_input->moving = sink_input_moving_cb;
1199 s->sink_input->suspend = sink_input_suspend_cb;
1200 s->sink_input->send_event = sink_input_send_event_cb;
1201 s->sink_input->userdata = s;
1202
1203 start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
1204
1205 fix_playback_buffer_attr(s);
1206
1207 pa_sink_input_get_silence(sink_input, &silence);
1208 memblockq_name = pa_sprintf_malloc("native protocol playback stream memblockq [%u]", s->sink_input->index);
1209 s->memblockq = pa_memblockq_new(
1210 memblockq_name,
1211 start_index,
1212 s->buffer_attr.maxlength,
1213 s->buffer_attr.tlength,
1214 &sink_input->sample_spec,
1215 s->buffer_attr.prebuf,
1216 s->buffer_attr.minreq,
1217 0,
1218 &silence);
1219 pa_xfree(memblockq_name);
1220 pa_memblock_unref(silence.memblock);
1221
1222 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1223
1224 *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
1225
1226 #ifdef PROTOCOL_NATIVE_DEBUG
1227 pa_log("missing original: %li", (long int) *missing);
1228 #endif
1229
1230 *ss = s->sink_input->sample_spec;
1231 *map = s->sink_input->channel_map;
1232
1233 pa_idxset_put(c->output_streams, s, &s->index);
1234
1235 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1236 ((double) pa_bytes_to_usec(s->buffer_attr.tlength, &sink_input->sample_spec) + (double) s->configured_sink_latency) / PA_USEC_PER_MSEC,
1237 (double) pa_bytes_to_usec(s->buffer_attr.tlength-s->buffer_attr.minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1238 (double) pa_bytes_to_usec(s->buffer_attr.minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1239 (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
1240
1241 pa_sink_input_put(s->sink_input);
1242
1243 out:
1244 if (formats)
1245 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
1246
1247 return s;
1248 }
1249
1250 /* Called from IO context */
1251 static void playback_stream_request_bytes(playback_stream *s) {
1252 size_t m, minreq;
1253 int previous_missing;
1254
1255 playback_stream_assert_ref(s);
1256
1257 m = pa_memblockq_pop_missing(s->memblockq);
1258
1259 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
1260 /* (unsigned long) m, */
1261 /* pa_memblockq_get_tlength(s->memblockq), */
1262 /* pa_memblockq_get_minreq(s->memblockq), */
1263 /* pa_memblockq_get_length(s->memblockq), */
1264 /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
1265
1266 if (m <= 0)
1267 return;
1268
1269 #ifdef PROTOCOL_NATIVE_DEBUG
1270 pa_log("request_bytes(%lu)", (unsigned long) m);
1271 #endif
1272
1273 previous_missing = pa_atomic_add(&s->missing, (int) m);
1274 minreq = pa_memblockq_get_minreq(s->memblockq);
1275
1276 if (pa_memblockq_prebuf_active(s->memblockq) ||
1277 (previous_missing < (int) minreq && previous_missing + (int) m >= (int) minreq))
1278 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
1279 }
1280
1281 /* Called from main context */
1282 static void playback_stream_send_killed(playback_stream *p) {
1283 pa_tagstruct *t;
1284 playback_stream_assert_ref(p);
1285
1286 t = pa_tagstruct_new(NULL, 0);
1287 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
1288 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1289 pa_tagstruct_putu32(t, p->index);
1290 pa_pstream_send_tagstruct(p->connection->pstream, t);
1291 }
1292
1293 /* Called from main context */
1294 static int native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
1295 pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1296 pa_native_connection_assert_ref(c);
1297
1298 if (!c->protocol)
1299 return -1;
1300
1301 switch (code) {
1302
1303 case CONNECTION_MESSAGE_REVOKE:
1304 pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
1305 break;
1306
1307 case CONNECTION_MESSAGE_RELEASE:
1308 pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
1309 break;
1310 }
1311
1312 return 0;
1313 }
1314
1315 /* Called from main context */
1316 static void native_connection_unlink(pa_native_connection *c) {
1317 record_stream *r;
1318 output_stream *o;
1319
1320 pa_assert(c);
1321
1322 if (!c->protocol)
1323 return;
1324
1325 pa_hook_fire(&c->protocol->hooks[PA_NATIVE_HOOK_CONNECTION_UNLINK], c);
1326
1327 if (c->options)
1328 pa_native_options_unref(c->options);
1329
1330 while ((r = pa_idxset_first(c->record_streams, NULL)))
1331 record_stream_unlink(r);
1332
1333 while ((o = pa_idxset_first(c->output_streams, NULL)))
1334 if (playback_stream_isinstance(o))
1335 playback_stream_unlink(PLAYBACK_STREAM(o));
1336 else
1337 upload_stream_unlink(UPLOAD_STREAM(o));
1338
1339 if (c->subscription)
1340 pa_subscription_free(c->subscription);
1341
1342 if (c->pstream)
1343 pa_pstream_unlink(c->pstream);
1344
1345 if (c->auth_timeout_event) {
1346 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
1347 c->auth_timeout_event = NULL;
1348 }
1349
1350 pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
1351 c->protocol = NULL;
1352 pa_native_connection_unref(c);
1353 }
1354
1355 /* Called from main context */
1356 static void native_connection_free(pa_object *o) {
1357 pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1358
1359 pa_assert(c);
1360
1361 native_connection_unlink(c);
1362
1363 pa_idxset_free(c->record_streams, NULL);
1364 pa_idxset_free(c->output_streams, NULL);
1365
1366 pa_pdispatch_unref(c->pdispatch);
1367 pa_pstream_unref(c->pstream);
1368 pa_client_free(c->client);
1369
1370 pa_xfree(c);
1371 }
1372
1373 /* Called from main context */
1374 static void native_connection_send_memblock(pa_native_connection *c) {
1375 uint32_t start;
1376 record_stream *r;
1377
1378 start = PA_IDXSET_INVALID;
1379 for (;;) {
1380 pa_memchunk chunk;
1381
1382 if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
1383 return;
1384
1385 if (start == PA_IDXSET_INVALID)
1386 start = c->rrobin_index;
1387 else if (start == c->rrobin_index)
1388 return;
1389
1390 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
1391 pa_memchunk schunk = chunk;
1392
1393 if (schunk.length > r->buffer_attr.fragsize)
1394 schunk.length = r->buffer_attr.fragsize;
1395
1396 pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
1397
1398 pa_memblockq_drop(r->memblockq, schunk.length);
1399 pa_memblock_unref(schunk.memblock);
1400
1401 return;
1402 }
1403 }
1404 }
1405
1406 /*** sink input callbacks ***/
1407
1408 /* Called from thread context */
1409 static void handle_seek(playback_stream *s, int64_t indexw) {
1410 playback_stream_assert_ref(s);
1411
1412 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1413
1414 if (s->sink_input->thread_info.underrun_for > 0) {
1415
1416 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1417
1418 if (pa_memblockq_is_readable(s->memblockq)) {
1419
1420 /* We just ended an underrun, let's ask the sink
1421 * for a complete rewind rewrite */
1422
1423 pa_log_debug("Requesting rewind due to end of underrun.");
1424 pa_sink_input_request_rewind(s->sink_input,
1425 (size_t) (s->sink_input->thread_info.underrun_for == (uint64_t) -1 ? 0 :
1426 s->sink_input->thread_info.underrun_for),
1427 false, true, false);
1428 }
1429
1430 } else {
1431 int64_t indexr;
1432
1433 indexr = pa_memblockq_get_read_index(s->memblockq);
1434
1435 if (indexw < indexr) {
1436 /* OK, the sink already asked for this data, so
1437 * let's have it ask us again */
1438
1439 pa_log_debug("Requesting rewind due to rewrite.");
1440 pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), true, false, false);
1441 }
1442 }
1443
1444 playback_stream_request_bytes(s);
1445 }
1446
1447 static void flush_write_no_account(pa_memblockq *q) {
1448 pa_memblockq_flush_write(q, false);
1449 }
1450
1451 /* Called from thread context */
1452 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1453 pa_sink_input *i = PA_SINK_INPUT(o);
1454 playback_stream *s;
1455
1456 pa_sink_input_assert_ref(i);
1457 s = PLAYBACK_STREAM(i->userdata);
1458 playback_stream_assert_ref(s);
1459
1460 switch (code) {
1461
1462 case SINK_INPUT_MESSAGE_SEEK:
1463 case SINK_INPUT_MESSAGE_POST_DATA: {
1464 int64_t windex = pa_memblockq_get_write_index(s->memblockq);
1465
1466 if (code == SINK_INPUT_MESSAGE_SEEK) {
1467 /* The client side is incapable of accounting correctly
1468 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1469 * able to deal with that. */
1470
1471 pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata), PA_PTR_TO_UINT(userdata) == PA_SEEK_RELATIVE);
1472 windex = PA_MIN(windex, pa_memblockq_get_write_index(s->memblockq));
1473 }
1474
1475 if (chunk && pa_memblockq_push_align(s->memblockq, chunk) < 0) {
1476 if (pa_log_ratelimit(PA_LOG_WARN))
1477 pa_log_warn("Failed to push data into queue");
1478 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
1479 pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, true);
1480 }
1481
1482 /* If more data is in queue, we rewind later instead. */
1483 if (s->seek_windex != -1)
1484 windex = PA_MIN(windex, s->seek_windex);
1485 if (pa_atomic_dec(&s->seek_or_post_in_queue) > 1)
1486 s->seek_windex = windex;
1487 else {
1488 s->seek_windex = -1;
1489 handle_seek(s, windex);
1490 }
1491 return 0;
1492 }
1493
1494 case SINK_INPUT_MESSAGE_DRAIN:
1495 case SINK_INPUT_MESSAGE_FLUSH:
1496 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1497 case SINK_INPUT_MESSAGE_TRIGGER: {
1498
1499 int64_t windex;
1500 pa_sink_input *isync;
1501 void (*func)(pa_memblockq *bq);
1502
1503 switch (code) {
1504 case SINK_INPUT_MESSAGE_FLUSH:
1505 func = flush_write_no_account;
1506 break;
1507
1508 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1509 func = pa_memblockq_prebuf_force;
1510 break;
1511
1512 case SINK_INPUT_MESSAGE_DRAIN:
1513 case SINK_INPUT_MESSAGE_TRIGGER:
1514 func = pa_memblockq_prebuf_disable;
1515 break;
1516
1517 default:
1518 pa_assert_not_reached();
1519 }
1520
1521 windex = pa_memblockq_get_write_index(s->memblockq);
1522 func(s->memblockq);
1523 handle_seek(s, windex);
1524
1525 /* Do the same for all other members in the sync group */
1526 for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
1527 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1528 windex = pa_memblockq_get_write_index(ssync->memblockq);
1529 func(ssync->memblockq);
1530 handle_seek(ssync, windex);
1531 }
1532
1533 for (isync = i->sync_next; isync; isync = isync->sync_next) {
1534 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1535 windex = pa_memblockq_get_write_index(ssync->memblockq);
1536 func(ssync->memblockq);
1537 handle_seek(ssync, windex);
1538 }
1539
1540 if (code == SINK_INPUT_MESSAGE_DRAIN) {
1541 if (!pa_memblockq_is_readable(s->memblockq))
1542 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
1543 else {
1544 s->drain_tag = PA_PTR_TO_UINT(userdata);
1545 s->drain_request = true;
1546 }
1547 }
1548
1549 return 0;
1550 }
1551
1552 case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
1553 /* Atomically get a snapshot of all timing parameters... */
1554 s->read_index = pa_memblockq_get_read_index(s->memblockq);
1555 s->write_index = pa_memblockq_get_write_index(s->memblockq);
1556 s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
1557 s->current_sink_latency = pa_sink_get_latency_within_thread(s->sink_input->sink);
1558 s->underrun_for = s->sink_input->thread_info.underrun_for;
1559 s->playing_for = s->sink_input->thread_info.playing_for;
1560
1561 return 0;
1562
1563 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1564 int64_t windex;
1565
1566 windex = pa_memblockq_get_write_index(s->memblockq);
1567
1568 /* We enable prebuffering so that after CORKED -> RUNNING
1569 * transitions we don't have trouble with underruns in case the
1570 * buffer has too little data. This must not be done when draining
1571 * has been requested, however, otherwise the buffered audio would
1572 * never play. */
1573 if (!s->drain_request)
1574 pa_memblockq_prebuf_force(s->memblockq);
1575
1576 handle_seek(s, windex);
1577
1578 /* Fall through to the default handler */
1579 break;
1580 }
1581
1582 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1583 pa_usec_t *r = userdata;
1584
1585 *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
1586
1587 /* Fall through, the default handler will add in the extra
1588 * latency added by the resampler */
1589 break;
1590 }
1591
1592 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR: {
1593 pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1594 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1595 return 0;
1596 }
1597 }
1598
1599 return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1600 }
1601
1602 static bool handle_input_underrun(playback_stream *s, bool force) {
1603 bool send_drain;
1604
1605 if (pa_memblockq_is_readable(s->memblockq))
1606 return false;
1607
1608 if (!s->is_underrun)
1609 pa_log_debug("%s %s of '%s'", force ? "Actual" : "Implicit",
1610 s->drain_request ? "drain" : "underrun", pa_strnull(pa_proplist_gets(s->sink_input->proplist, PA_PROP_MEDIA_NAME)));
1611
1612 send_drain = s->drain_request && (force || pa_sink_input_safe_to_remove(s->sink_input));
1613
1614 if (send_drain) {
1615 s->drain_request = false;
1616 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);
1617 pa_log_debug("Drain acknowledged of '%s'", pa_strnull(pa_proplist_gets(s->sink_input->proplist, PA_PROP_MEDIA_NAME)));
1618 } else if (!s->is_underrun) {
1619 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, pa_memblockq_get_read_index(s->memblockq), NULL, NULL);
1620 }
1621 s->is_underrun = true;
1622 playback_stream_request_bytes(s);
1623 return true;
1624 }
1625
1626 /* Called from thread context */
1627 static bool sink_input_process_underrun_cb(pa_sink_input *i) {
1628 playback_stream *s;
1629
1630 pa_sink_input_assert_ref(i);
1631 s = PLAYBACK_STREAM(i->userdata);
1632 playback_stream_assert_ref(s);
1633
1634 return handle_input_underrun(s, true);
1635 }
1636
1637 /* Called from thread context */
1638 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
1639 playback_stream *s;
1640
1641 pa_sink_input_assert_ref(i);
1642 s = PLAYBACK_STREAM(i->userdata);
1643 playback_stream_assert_ref(s);
1644 pa_assert(chunk);
1645
1646 #ifdef PROTOCOL_NATIVE_DEBUG
1647 pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq));
1648 #endif
1649
1650 if (!handle_input_underrun(s, false))
1651 s->is_underrun = false;
1652
1653 /* This call will not fail with prebuf=0, hence we check for
1654 underrun explicitly in handle_input_underrun */
1655 if (pa_memblockq_peek(s->memblockq, chunk) < 0)
1656 return -1;
1657
1658 chunk->length = PA_MIN(nbytes, chunk->length);
1659
1660 if (i->thread_info.underrun_for > 0)
1661 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
1662
1663 pa_memblockq_drop(s->memblockq, chunk->length);
1664 playback_stream_request_bytes(s);
1665
1666 return 0;
1667 }
1668
1669 /* Called from thread context */
1670 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1671 playback_stream *s;
1672
1673 pa_sink_input_assert_ref(i);
1674 s = PLAYBACK_STREAM(i->userdata);
1675 playback_stream_assert_ref(s);
1676
1677 /* If we are in an underrun, then we don't rewind */
1678 if (i->thread_info.underrun_for > 0)
1679 return;
1680
1681 pa_memblockq_rewind(s->memblockq, nbytes);
1682 }
1683
1684 /* Called from thread context */
1685 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1686 playback_stream *s;
1687
1688 pa_sink_input_assert_ref(i);
1689 s = PLAYBACK_STREAM(i->userdata);
1690 playback_stream_assert_ref(s);
1691
1692 pa_memblockq_set_maxrewind(s->memblockq, nbytes);
1693 }
1694
1695 /* Called from thread context */
1696 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
1697 playback_stream *s;
1698 size_t new_tlength, old_tlength;
1699
1700 pa_sink_input_assert_ref(i);
1701 s = PLAYBACK_STREAM(i->userdata);
1702 playback_stream_assert_ref(s);
1703
1704 old_tlength = pa_memblockq_get_tlength(s->memblockq);
1705 new_tlength = nbytes+2*pa_memblockq_get_minreq(s->memblockq);
1706
1707 if (old_tlength < new_tlength) {
1708 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength, new_tlength);
1709 pa_memblockq_set_tlength(s->memblockq, new_tlength);
1710 new_tlength = pa_memblockq_get_tlength(s->memblockq);
1711
1712 if (new_tlength == old_tlength)
1713 pa_log_debug("Failed to increase tlength");
1714 else {
1715 pa_log_debug("Notifying client about increased tlength");
1716 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);
1717 }
1718 }
1719 }
1720
1721 /* Called from main context */
1722 static void sink_input_kill_cb(pa_sink_input *i) {
1723 playback_stream *s;
1724
1725 pa_sink_input_assert_ref(i);
1726 s = PLAYBACK_STREAM(i->userdata);
1727 playback_stream_assert_ref(s);
1728
1729 playback_stream_send_killed(s);
1730 playback_stream_unlink(s);
1731 }
1732
1733 /* Called from main context */
1734 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl) {
1735 playback_stream *s;
1736 pa_tagstruct *t;
1737
1738 pa_sink_input_assert_ref(i);
1739 s = PLAYBACK_STREAM(i->userdata);
1740 playback_stream_assert_ref(s);
1741
1742 if (s->connection->version < 15)
1743 return;
1744
1745 t = pa_tagstruct_new(NULL, 0);
1746 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_EVENT);
1747 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1748 pa_tagstruct_putu32(t, s->index);
1749 pa_tagstruct_puts(t, event);
1750 pa_tagstruct_put_proplist(t, pl);
1751 pa_pstream_send_tagstruct(s->connection->pstream, t);
1752 }
1753
1754 /* Called from main context */
1755 static void sink_input_suspend_cb(pa_sink_input *i, bool suspend) {
1756 playback_stream *s;
1757 pa_tagstruct *t;
1758
1759 pa_sink_input_assert_ref(i);
1760 s = PLAYBACK_STREAM(i->userdata);
1761 playback_stream_assert_ref(s);
1762
1763 if (s->connection->version < 12)
1764 return;
1765
1766 t = pa_tagstruct_new(NULL, 0);
1767 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED);
1768 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1769 pa_tagstruct_putu32(t, s->index);
1770 pa_tagstruct_put_boolean(t, suspend);
1771 pa_pstream_send_tagstruct(s->connection->pstream, t);
1772 }
1773
1774 /* Called from main context */
1775 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1776 playback_stream *s;
1777 pa_tagstruct *t;
1778
1779 pa_sink_input_assert_ref(i);
1780 s = PLAYBACK_STREAM(i->userdata);
1781 playback_stream_assert_ref(s);
1782
1783 if (!dest)
1784 return;
1785
1786 fix_playback_buffer_attr(s);
1787 pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1788 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1789
1790 if (s->connection->version < 12)
1791 return;
1792
1793 t = pa_tagstruct_new(NULL, 0);
1794 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED);
1795 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1796 pa_tagstruct_putu32(t, s->index);
1797 pa_tagstruct_putu32(t, dest->index);
1798 pa_tagstruct_puts(t, dest->name);
1799 pa_tagstruct_put_boolean(t, pa_sink_get_state(dest) == PA_SINK_SUSPENDED);
1800
1801 if (s->connection->version >= 13) {
1802 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1803 pa_tagstruct_putu32(t, s->buffer_attr.tlength);
1804 pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
1805 pa_tagstruct_putu32(t, s->buffer_attr.minreq);
1806 pa_tagstruct_put_usec(t, s->configured_sink_latency);
1807 }
1808
1809 pa_pstream_send_tagstruct(s->connection->pstream, t);
1810 }
1811
1812 /*** source_output callbacks ***/
1813
1814 /* Called from thread context */
1815 static int source_output_process_msg(pa_msgobject *_o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1816 pa_source_output *o = PA_SOURCE_OUTPUT(_o);
1817 record_stream *s;
1818
1819 pa_source_output_assert_ref(o);
1820 s = RECORD_STREAM(o->userdata);
1821 record_stream_assert_ref(s);
1822
1823 switch (code) {
1824 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY:
1825 /* Atomically get a snapshot of all timing parameters... */
1826 s->current_monitor_latency = o->source->monitor_of ? pa_sink_get_latency_within_thread(o->source->monitor_of) : 0;
1827 s->current_source_latency = pa_source_get_latency_within_thread(o->source);
1828 s->on_the_fly_snapshot = pa_atomic_load(&s->on_the_fly);
1829 return 0;
1830 }
1831
1832 return pa_source_output_process_msg(_o, code, userdata, offset, chunk);
1833 }
1834
1835 /* Called from thread context */
1836 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1837 record_stream *s;
1838
1839 pa_source_output_assert_ref(o);
1840 s = RECORD_STREAM(o->userdata);
1841 record_stream_assert_ref(s);
1842 pa_assert(chunk);
1843
1844 pa_atomic_add(&s->on_the_fly, chunk->length);
1845 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1846 }
1847
1848 static void source_output_kill_cb(pa_source_output *o) {
1849 record_stream *s;
1850
1851 pa_source_output_assert_ref(o);
1852 s = RECORD_STREAM(o->userdata);
1853 record_stream_assert_ref(s);
1854
1855 record_stream_send_killed(s);
1856 record_stream_unlink(s);
1857 }
1858
1859 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1860 record_stream *s;
1861
1862 pa_source_output_assert_ref(o);
1863 s = RECORD_STREAM(o->userdata);
1864 record_stream_assert_ref(s);
1865
1866 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1867
1868 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
1869 }
1870
1871 /* Called from main context */
1872 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl) {
1873 record_stream *s;
1874 pa_tagstruct *t;
1875
1876 pa_source_output_assert_ref(o);
1877 s = RECORD_STREAM(o->userdata);
1878 record_stream_assert_ref(s);
1879
1880 if (s->connection->version < 15)
1881 return;
1882
1883 t = pa_tagstruct_new(NULL, 0);
1884 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_EVENT);
1885 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1886 pa_tagstruct_putu32(t, s->index);
1887 pa_tagstruct_puts(t, event);
1888 pa_tagstruct_put_proplist(t, pl);
1889 pa_pstream_send_tagstruct(s->connection->pstream, t);
1890 }
1891
1892 /* Called from main context */
1893 static void source_output_suspend_cb(pa_source_output *o, bool suspend) {
1894 record_stream *s;
1895 pa_tagstruct *t;
1896
1897 pa_source_output_assert_ref(o);
1898 s = RECORD_STREAM(o->userdata);
1899 record_stream_assert_ref(s);
1900
1901 if (s->connection->version < 12)
1902 return;
1903
1904 t = pa_tagstruct_new(NULL, 0);
1905 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED);
1906 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1907 pa_tagstruct_putu32(t, s->index);
1908 pa_tagstruct_put_boolean(t, suspend);
1909 pa_pstream_send_tagstruct(s->connection->pstream, t);
1910 }
1911
1912 /* Called from main context */
1913 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
1914 record_stream *s;
1915 pa_tagstruct *t;
1916
1917 pa_source_output_assert_ref(o);
1918 s = RECORD_STREAM(o->userdata);
1919 record_stream_assert_ref(s);
1920
1921 if (!dest)
1922 return;
1923
1924 fix_record_buffer_attr_pre(s);
1925 pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
1926 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1927 fix_record_buffer_attr_post(s);
1928
1929 if (s->connection->version < 12)
1930 return;
1931
1932 t = pa_tagstruct_new(NULL, 0);
1933 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED);
1934 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1935 pa_tagstruct_putu32(t, s->index);
1936 pa_tagstruct_putu32(t, dest->index);
1937 pa_tagstruct_puts(t, dest->name);
1938 pa_tagstruct_put_boolean(t, pa_source_get_state(dest) == PA_SOURCE_SUSPENDED);
1939
1940 if (s->connection->version >= 13) {
1941 pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1942 pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
1943 pa_tagstruct_put_usec(t, s->configured_source_latency);
1944 }
1945
1946 pa_pstream_send_tagstruct(s->connection->pstream, t);
1947 }
1948
1949 /*** pdispatch callbacks ***/
1950
1951 static void protocol_error(pa_native_connection *c) {
1952 pa_log("protocol error, kicking client");
1953 native_connection_unlink(c);
1954 }
1955
1956 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1957 if (!(expression)) { \
1958 pa_pstream_send_error((pstream), (tag), (error)); \
1959 return; \
1960 } \
1961 } while(0);
1962
1963 #define CHECK_VALIDITY_GOTO(pstream, expression, tag, error, label) do { \
1964 if (!(expression)) { \
1965 pa_pstream_send_error((pstream), (tag), (error)); \
1966 goto label; \
1967 } \
1968 } while(0);
1969
1970 static pa_tagstruct *reply_new(uint32_t tag) {
1971 pa_tagstruct *reply;
1972
1973 reply = pa_tagstruct_new(NULL, 0);
1974 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1975 pa_tagstruct_putu32(reply, tag);
1976 return reply;
1977 }
1978
1979 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1980 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
1981 playback_stream *s;
1982 uint32_t sink_index, syncid, missing = 0;
1983 pa_buffer_attr attr;
1984 const char *name = NULL, *sink_name;
1985 pa_sample_spec ss;
1986 pa_channel_map map;
1987 pa_tagstruct *reply;
1988 pa_sink *sink = NULL;
1989 pa_cvolume volume;
1990 bool
1991 corked = false,
1992 no_remap = false,
1993 no_remix = false,
1994 fix_format = false,
1995 fix_rate = false,
1996 fix_channels = false,
1997 no_move = false,
1998 variable_rate = false,
1999 muted = false,
2000 adjust_latency = false,
2001 early_requests = false,
2002 dont_inhibit_auto_suspend = false,
2003 volume_set = true,
2004 muted_set = false,
2005 fail_on_suspend = false,
2006 relative_volume = false,
2007 passthrough = false;
2008
2009 pa_sink_input_flags_t flags = 0;
2010 pa_proplist *p = NULL;
2011 int ret = PA_ERR_INVALID;
2012 uint8_t n_formats = 0;
2013 pa_format_info *format;
2014 pa_idxset *formats = NULL;
2015 uint32_t i;
2016
2017 pa_native_connection_assert_ref(c);
2018 pa_assert(t);
2019 memset(&attr, 0, sizeof(attr));
2020
2021 if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
2022 pa_tagstruct_get(
2023 t,
2024 PA_TAG_SAMPLE_SPEC, &ss,
2025 PA_TAG_CHANNEL_MAP, &map,
2026 PA_TAG_U32, &sink_index,
2027 PA_TAG_STRING, &sink_name,
2028 PA_TAG_U32, &attr.maxlength,
2029 PA_TAG_BOOLEAN, &corked,
2030 PA_TAG_U32, &attr.tlength,
2031 PA_TAG_U32, &attr.prebuf,
2032 PA_TAG_U32, &attr.minreq,
2033 PA_TAG_U32, &syncid,
2034 PA_TAG_CVOLUME, &volume,
2035 PA_TAG_INVALID) < 0) {
2036
2037 protocol_error(c);
2038 goto finish;
2039 }
2040
2041 CHECK_VALIDITY_GOTO(c->pstream, c->authorized, tag, PA_ERR_ACCESS, finish);
2042 CHECK_VALIDITY_GOTO(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID, finish);
2043 CHECK_VALIDITY_GOTO(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID, finish);
2044 CHECK_VALIDITY_GOTO(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID, finish);
2045 CHECK_VALIDITY_GOTO(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID, finish);
2046
2047 p = pa_proplist_new();
2048
2049 if (name)
2050 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2051
2052 if (c->version >= 12) {
2053 /* Since 0.9.8 the user can ask for a couple of additional flags */
2054
2055 if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
2056 pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
2057 pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
2058 pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
2059 pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
2060 pa_tagstruct_get_boolean(t, &no_move) < 0 ||
2061 pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
2062
2063 protocol_error(c);
2064 goto finish;
2065 }
2066 }
2067
2068 if (c->version >= 13) {
2069
2070 if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
2071 pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
2072 pa_tagstruct_get_proplist(t, p) < 0) {
2073
2074 protocol_error(c);
2075 goto finish;
2076 }
2077 }
2078
2079 if (c->version >= 14) {
2080
2081 if (pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
2082 pa_tagstruct_get_boolean(t, &early_requests) < 0) {
2083
2084 protocol_error(c);
2085 goto finish;
2086 }
2087 }
2088
2089 if (c->version >= 15) {
2090
2091 if (pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
2092 pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
2093 pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
2094
2095 protocol_error(c);
2096 goto finish;
2097 }
2098 }
2099
2100 if (c->version >= 17) {
2101
2102 if (pa_tagstruct_get_boolean(t, &relative_volume) < 0) {
2103
2104 protocol_error(c);
2105 goto finish;
2106 }
2107 }
2108
2109 if (c->version >= 18) {
2110
2111 if (pa_tagstruct_get_boolean(t, &passthrough) < 0 ) {
2112 protocol_error(c);
2113 goto finish;
2114 }
2115 }
2116
2117 if (c->version >= 21) {
2118
2119 if (pa_tagstruct_getu8(t, &n_formats) < 0) {
2120 protocol_error(c);
2121 goto finish;
2122 }
2123
2124 if (n_formats)
2125 formats = pa_idxset_new(NULL, NULL);
2126
2127 for (i = 0; i < n_formats; i++) {
2128 format = pa_format_info_new();
2129 if (pa_tagstruct_get_format_info(t, format) < 0) {
2130 protocol_error(c);
2131 goto finish;
2132 }
2133 pa_idxset_put(formats, format, NULL);
2134 }
2135 }
2136
2137 if (n_formats == 0) {
2138 CHECK_VALIDITY_GOTO(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID, finish);
2139 CHECK_VALIDITY_GOTO(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID, finish);
2140 CHECK_VALIDITY_GOTO(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID, finish);
2141 } else {
2142 PA_IDXSET_FOREACH(format, formats, i) {
2143 CHECK_VALIDITY_GOTO(c->pstream, pa_format_info_valid(format), tag, PA_ERR_INVALID, finish);
2144 }
2145 }
2146
2147 if (!pa_tagstruct_eof(t)) {
2148 protocol_error(c);
2149 goto finish;
2150 }
2151
2152 if (sink_index != PA_INVALID_INDEX) {
2153
2154 if (!(sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index))) {
2155 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2156 goto finish;
2157 }
2158
2159 } else if (sink_name) {
2160
2161 if (!(sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK))) {
2162 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2163 goto finish;
2164 }
2165 }
2166
2167 flags =
2168 (corked ? PA_SINK_INPUT_START_CORKED : 0) |
2169 (no_remap ? PA_SINK_INPUT_NO_REMAP : 0) |
2170 (no_remix ? PA_SINK_INPUT_NO_REMIX : 0) |
2171 (fix_format ? PA_SINK_INPUT_FIX_FORMAT : 0) |
2172 (fix_rate ? PA_SINK_INPUT_FIX_RATE : 0) |
2173 (fix_channels ? PA_SINK_INPUT_FIX_CHANNELS : 0) |
2174 (no_move ? PA_SINK_INPUT_DONT_MOVE : 0) |
2175 (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0) |
2176 (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2177 (fail_on_suspend ? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND : 0) |
2178 (passthrough ? PA_SINK_INPUT_PASSTHROUGH : 0);
2179
2180 /* Only since protocol version 15 there's a separate muted_set
2181 * flag. For older versions we synthesize it here */
2182 muted_set = muted_set || muted;
2183
2184 s = playback_stream_new(c, sink, &ss, &map, formats, &attr, volume_set ? &volume : NULL, muted, muted_set, flags, p, adjust_latency, early_requests, relative_volume, syncid, &missing, &ret);
2185 /* We no longer own the formats idxset */
2186 formats = NULL;
2187
2188 CHECK_VALIDITY_GOTO(c->pstream, s, tag, ret, finish);
2189
2190 reply = reply_new(tag);
2191 pa_tagstruct_putu32(reply, s->index);
2192 pa_assert(s->sink_input);
2193 pa_tagstruct_putu32(reply, s->sink_input->index);
2194 pa_tagstruct_putu32(reply, missing);
2195
2196 #ifdef PROTOCOL_NATIVE_DEBUG
2197 pa_log("initial request is %u", missing);
2198 #endif
2199
2200 if (c->version >= 9) {
2201 /* Since 0.9.0 we support sending the buffer metrics back to the client */
2202
2203 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2204 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.tlength);
2205 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.prebuf);
2206 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.minreq);
2207 }
2208
2209 if (c->version >= 12) {
2210 /* Since 0.9.8 we support sending the chosen sample
2211 * spec/channel map/device/suspend status back to the
2212 * client */
2213
2214 pa_tagstruct_put_sample_spec(reply, &ss);
2215 pa_tagstruct_put_channel_map(reply, &map);
2216
2217 pa_tagstruct_putu32(reply, s->sink_input->sink->index);
2218 pa_tagstruct_puts(reply, s->sink_input->sink->name);
2219
2220 pa_tagstruct_put_boolean(reply, pa_sink_get_state(s->sink_input->sink) == PA_SINK_SUSPENDED);
2221 }
2222
2223 if (c->version >= 13)
2224 pa_tagstruct_put_usec(reply, s->configured_sink_latency);
2225
2226 if (c->version >= 21) {
2227 /* Send back the format we negotiated */
2228 if (s->sink_input->format)
2229 pa_tagstruct_put_format_info(reply, s->sink_input->format);
2230 else {
2231 pa_format_info *f = pa_format_info_new();
2232 pa_tagstruct_put_format_info(reply, f);
2233 pa_format_info_free(f);
2234 }
2235 }
2236
2237 pa_pstream_send_tagstruct(c->pstream, reply);
2238
2239 finish:
2240 if (p)
2241 pa_proplist_free(p);
2242 if (formats)
2243 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
2244 }
2245
2246 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2247 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2248 uint32_t channel;
2249
2250 pa_native_connection_assert_ref(c);
2251 pa_assert(t);
2252
2253 if (pa_tagstruct_getu32(t, &channel) < 0 ||
2254 !pa_tagstruct_eof(t)) {
2255 protocol_error(c);
2256 return;
2257 }
2258
2259 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2260
2261 switch (command) {
2262
2263 case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
2264 playback_stream *s;
2265 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
2266 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2267 return;
2268 }
2269
2270 playback_stream_unlink(s);
2271 break;
2272 }
2273
2274 case PA_COMMAND_DELETE_RECORD_STREAM: {
2275 record_stream *s;
2276 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
2277 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2278 return;
2279 }
2280
2281 record_stream_unlink(s);
2282 break;
2283 }
2284
2285 case PA_COMMAND_DELETE_UPLOAD_STREAM: {
2286 upload_stream *s;
2287
2288 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
2289 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2290 return;
2291 }
2292
2293 upload_stream_unlink(s);
2294 break;
2295 }
2296
2297 default:
2298 pa_assert_not_reached();
2299 }
2300
2301 pa_pstream_send_simple_ack(c->pstream, tag);
2302 }
2303
2304 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2305 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2306 record_stream *s;
2307 pa_buffer_attr attr;
2308 uint32_t source_index;
2309 const char *name = NULL, *source_name;
2310 pa_sample_spec ss;
2311 pa_channel_map map;
2312 pa_tagstruct *reply;
2313 pa_source *source = NULL;
2314 pa_cvolume volume;
2315 bool
2316 corked = false,
2317 no_remap = false,
2318 no_remix = false,
2319 fix_format = false,
2320 fix_rate = false,
2321 fix_channels = false,
2322 no_move = false,
2323 variable_rate = false,
2324 muted = false,
2325 adjust_latency = false,
2326 peak_detect = false,
2327 early_requests = false,
2328 dont_inhibit_auto_suspend = false,
2329 volume_set = false,
2330 muted_set = false,
2331 fail_on_suspend = false,
2332 relative_volume = false,
2333 passthrough = false;
2334
2335 pa_source_output_flags_t flags = 0;
2336 pa_proplist *p = NULL;
2337 uint32_t direct_on_input_idx = PA_INVALID_INDEX;
2338 pa_sink_input *direct_on_input = NULL;
2339 int ret = PA_ERR_INVALID;
2340 uint8_t n_formats = 0;
2341 pa_format_info *format;
2342 pa_idxset *formats = NULL;
2343 uint32_t i;
2344
2345 pa_native_connection_assert_ref(c);
2346 pa_assert(t);
2347
2348 memset(&attr, 0, sizeof(attr));
2349
2350 if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
2351 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2352 pa_tagstruct_get_channel_map(t, &map) < 0 ||
2353 pa_tagstruct_getu32(t, &source_index) < 0 ||
2354 pa_tagstruct_gets(t, &source_name) < 0 ||
2355 pa_tagstruct_getu32(t, &attr.maxlength) < 0 ||
2356 pa_tagstruct_get_boolean(t, &corked) < 0 ||
2357 pa_tagstruct_getu32(t, &attr.fragsize) < 0) {
2358
2359 protocol_error(c);
2360 goto finish;
2361 }
2362
2363 CHECK_VALIDITY_GOTO(c->pstream, c->authorized, tag, PA_ERR_ACCESS, finish);
2364 CHECK_VALIDITY_GOTO(c->pstream, !source_name || pa_namereg_is_valid_name_or_wildcard(source_name, PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID, finish);
2365 CHECK_VALIDITY_GOTO(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID, finish);
2366 CHECK_VALIDITY_GOTO(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID, finish);
2367
2368 p = pa_proplist_new();
2369
2370 if (name)
2371 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2372
2373 if (c->version >= 12) {
2374 /* Since 0.9.8 the user can ask for a couple of additional flags */
2375
2376 if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
2377 pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
2378 pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
2379 pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
2380 pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
2381 pa_tagstruct_get_boolean(t, &no_move) < 0 ||
2382 pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
2383
2384 protocol_error(c);
2385 goto finish;
2386 }
2387 }
2388
2389 if (c->version >= 13) {
2390
2391 if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
2392 pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
2393 pa_tagstruct_get_proplist(t, p) < 0 ||
2394 pa_tagstruct_getu32(t, &direct_on_input_idx) < 0) {
2395
2396 protocol_error(c);
2397 goto finish;
2398 }
2399 }
2400
2401 if (c->version >= 14) {
2402
2403 if (pa_tagstruct_get_boolean(t, &early_requests) < 0) {
2404 protocol_error(c);
2405 goto finish;
2406 }
2407 }
2408
2409 if (c->version >= 15) {
2410
2411 if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
2412 pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
2413
2414 protocol_error(c);
2415 goto finish;
2416 }
2417 }
2418
2419 if (c->version >= 22) {
2420 /* For newer client versions (with per-source-output volumes), we try
2421 * to make the behaviour for playback and record streams the same. */
2422 volume_set = true;
2423
2424 if (pa_tagstruct_getu8(t, &n_formats) < 0) {
2425 protocol_error(c);
2426 goto finish;
2427 }
2428
2429 if (n_formats)
2430 formats = pa_idxset_new(NULL, NULL);
2431
2432 for (i = 0; i < n_formats; i++) {
2433 format = pa_format_info_new();
2434 if (pa_tagstruct_get_format_info(t, format) < 0) {
2435 protocol_error(c);
2436 goto finish;
2437 }
2438 pa_idxset_put(formats, format, NULL);
2439 }
2440
2441 if (pa_tagstruct_get_cvolume(t, &volume) < 0 ||
2442 pa_tagstruct_get_boolean(t, &muted) < 0 ||
2443 pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
2444 pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
2445 pa_tagstruct_get_boolean(t, &relative_volume) < 0 ||
2446 pa_tagstruct_get_boolean(t, &passthrough) < 0) {
2447
2448 protocol_error(c);
2449 goto finish;
2450 }
2451
2452 CHECK_VALIDITY_GOTO(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID, finish);
2453 }
2454
2455 if (n_formats == 0) {
2456 CHECK_VALIDITY_GOTO(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID, finish);
2457 CHECK_VALIDITY_GOTO(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID, finish);
2458 CHECK_VALIDITY_GOTO(c->pstream, c->version < 22 || (volume.channels == ss.channels), tag, PA_ERR_INVALID, finish);
2459 CHECK_VALIDITY_GOTO(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID, finish);
2460 } else {
2461 PA_IDXSET_FOREACH(format, formats, i) {
2462 CHECK_VALIDITY_GOTO(c->pstream, pa_format_info_valid(format), tag, PA_ERR_INVALID, finish);
2463 }
2464 }
2465
2466 if (!pa_tagstruct_eof(t)) {
2467 protocol_error(c);
2468 goto finish;
2469 }
2470
2471 if (source_index != PA_INVALID_INDEX) {
2472
2473 if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
2474 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2475 goto finish;
2476 }
2477
2478 } else if (source_name) {
2479
2480 if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE))) {
2481 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2482 goto finish;
2483 }
2484 }
2485
2486 if (direct_on_input_idx != PA_INVALID_INDEX) {
2487
2488 if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
2489 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2490 goto finish;
2491 }
2492 }
2493
2494 flags =
2495 (corked ? PA_SOURCE_OUTPUT_START_CORKED : 0) |
2496 (no_remap ? PA_SOURCE_OUTPUT_NO_REMAP : 0) |
2497 (no_remix ? PA_SOURCE_OUTPUT_NO_REMIX : 0) |
2498 (fix_format ? PA_SOURCE_OUTPUT_FIX_FORMAT : 0) |
2499 (fix_rate ? PA_SOURCE_OUTPUT_FIX_RATE : 0) |
2500 (fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
2501 (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
2502 (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
2503 (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2504 (fail_on_suspend ? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND : 0) |
2505 (passthrough ? PA_SOURCE_OUTPUT_PASSTHROUGH : 0);
2506
2507 s = record_stream_new(c, source, &ss, &map, formats, &attr, volume_set ? &volume : NULL, muted, muted_set, flags, p, adjust_latency, early_requests, relative_volume, peak_detect, direct_on_input, &ret);
2508
2509 CHECK_VALIDITY_GOTO(c->pstream, s, tag, ret, finish);
2510
2511 reply = reply_new(tag);
2512 pa_tagstruct_putu32(reply, s->index);
2513 pa_assert(s->source_output);
2514 pa_tagstruct_putu32(reply, s->source_output->index);
2515
2516 if (c->version >= 9) {
2517 /* Since 0.9 we support sending the buffer metrics back to the client */
2518
2519 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2520 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.fragsize);
2521 }
2522
2523 if (c->version >= 12) {
2524 /* Since 0.9.8 we support sending the chosen sample
2525 * spec/channel map/device/suspend status back to the
2526 * client */
2527
2528 pa_tagstruct_put_sample_spec(reply, &ss);
2529 pa_tagstruct_put_channel_map(reply, &map);
2530
2531 pa_tagstruct_putu32(reply, s->source_output->source->index);
2532 pa_tagstruct_puts(reply, s->source_output->source->name);
2533
2534 pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED);
2535 }
2536
2537 if (c->version >= 13)
2538 pa_tagstruct_put_usec(reply, s->configured_source_latency);
2539
2540 if (c->version >= 22) {
2541 /* Send back the format we negotiated */
2542 if (s->source_output->format)
2543 pa_tagstruct_put_format_info(reply, s->source_output->format);
2544 else {
2545 pa_format_info *f = pa_format_info_new();
2546 pa_tagstruct_put_format_info(reply, f);
2547 pa_format_info_free(f);
2548 }
2549 }
2550
2551 pa_pstream_send_tagstruct(c->pstream, reply);
2552
2553 finish:
2554 if (p)
2555 pa_proplist_free(p);
2556 if (formats)
2557 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
2558 }
2559
2560 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2561 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2562 int ret;
2563
2564 pa_native_connection_assert_ref(c);
2565 pa_assert(t);
2566
2567 if (!pa_tagstruct_eof(t)) {
2568 protocol_error(c);
2569 return;
2570 }
2571
2572 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2573 ret = pa_core_exit(c->protocol->core, false, 0);
2574 CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
2575
2576 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)));
2577
2578 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
2579 }
2580
2581 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2582 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2583 const void*cookie;
2584 pa_tagstruct *reply;
2585 bool shm_on_remote = false, do_shm;
2586
2587 pa_native_connection_assert_ref(c);
2588 pa_assert(t);
2589
2590 if (pa_tagstruct_getu32(t, &c->version) < 0 ||
2591 pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
2592 !pa_tagstruct_eof(t)) {
2593 protocol_error(c);
2594 return;
2595 }
2596
2597 /* Minimum supported version */
2598 if (c->version < 8) {
2599 pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
2600 return;
2601 }
2602
2603 /* Starting with protocol version 13 the MSB of the version tag
2604 reflects if shm is available for this pa_native_connection or
2605 not. */
2606 if (c->version >= 13) {
2607 shm_on_remote = !!(c->version & 0x80000000U);
2608 c->version &= 0x7FFFFFFFU;
2609 }
2610
2611 pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
2612
2613 pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
2614
2615 if (!c->authorized) {
2616 bool success = false;
2617
2618 #ifdef HAVE_CREDS
2619 const pa_creds *creds;
2620
2621 if ((creds = pa_pdispatch_creds(pd))) {
2622 if (creds->uid == getuid())
2623 success = true;
2624 else if (c->options->auth_group) {
2625 int r;
2626 gid_t gid;
2627
2628 if ((gid = pa_get_gid_of_group(c->options->auth_group)) == (gid_t) -1)
2629 pa_log_warn("Failed to get GID of group '%s'", c->options->auth_group);
2630 else if (gid == creds->gid)
2631 success = true;
2632
2633 if (!success) {
2634 if ((r = pa_uid_in_group(creds->uid, c->options->auth_group)) < 0)
2635 pa_log_warn("Failed to check group membership.");
2636 else if (r > 0)
2637 success = true;
2638 }
2639 }
2640
2641 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2642 (unsigned long) creds->uid,
2643 (unsigned long) creds->gid,
2644 (int) success);
2645 }
2646 #endif
2647
2648 if (!success && c->options->auth_cookie) {
2649 const uint8_t *ac;
2650
2651 if ((ac = pa_auth_cookie_read(c->options->auth_cookie, PA_NATIVE_COOKIE_LENGTH)))
2652 if (memcmp(ac, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
2653 success = true;
2654 }
2655
2656 if (!success) {
2657 pa_log_warn("Denied access to client with invalid authorization data.");
2658 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2659 return;
2660 }
2661
2662 c->authorized = true;
2663 if (c->auth_timeout_event) {
2664 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
2665 c->auth_timeout_event = NULL;
2666 }
2667 }
2668
2669 /* Enable shared memory support if possible */
2670 do_shm =
2671 pa_mempool_is_shared(c->protocol->core->mempool) &&
2672 c->is_local;
2673
2674 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm));
2675
2676 if (do_shm)
2677 if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
2678 do_shm = false;
2679
2680 #ifdef HAVE_CREDS
2681 if (do_shm) {
2682 /* Only enable SHM if both sides are owned by the same
2683 * user. This is a security measure because otherwise data
2684 * private to the user might leak. */
2685
2686 const pa_creds *creds;
2687 if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
2688 do_shm = false;
2689 }
2690 #endif
2691
2692 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
2693 pa_pstream_enable_shm(c->pstream, do_shm);
2694
2695 reply = reply_new(tag);
2696 pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0));
2697
2698 #ifdef HAVE_CREDS
2699 {
2700 /* SHM support is only enabled after both sides made sure they are the same user. */
2701
2702 pa_creds ucred;
2703
2704 ucred.uid = getuid();
2705 ucred.gid = getgid();
2706
2707 pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
2708 }
2709 #else
2710 pa_pstream_send_tagstruct(c->pstream, reply);
2711 #endif
2712 }
2713
2714 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2715 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2716 const char *name = NULL;
2717 pa_proplist *p;
2718 pa_tagstruct *reply;
2719
2720 pa_native_connection_assert_ref(c);
2721 pa_assert(t);
2722
2723 p = pa_proplist_new();
2724
2725 if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
2726 (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2727 !pa_tagstruct_eof(t)) {
2728
2729 protocol_error(c);
2730 pa_proplist_free(p);
2731 return;
2732 }
2733
2734 if (name)
2735 if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
2736 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2737 pa_proplist_free(p);
2738 return;
2739 }
2740
2741 pa_client_update_proplist(c->client, PA_UPDATE_REPLACE, p);
2742 pa_proplist_free(p);
2743
2744 reply = reply_new(tag);
2745
2746 if (c->version >= 13)
2747 pa_tagstruct_putu32(reply, c->client->index);
2748
2749 pa_pstream_send_tagstruct(c->pstream, reply);
2750 }
2751
2752 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2753 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2754 const char *name;
2755 uint32_t idx = PA_IDXSET_INVALID;
2756
2757 pa_native_connection_assert_ref(c);
2758 pa_assert(t);
2759
2760 if (pa_tagstruct_gets(t, &name) < 0 ||
2761 !pa_tagstruct_eof(t)) {
2762 protocol_error(c);
2763 return;
2764 }
2765
2766 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2767 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);
2768
2769 if (command == PA_COMMAND_LOOKUP_SINK) {
2770 pa_sink *sink;
2771 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK)))
2772 idx = sink->index;
2773 } else {
2774 pa_source *source;
2775 pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
2776 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE)))
2777 idx = source->index;
2778 }
2779
2780 if (idx == PA_IDXSET_INVALID)
2781 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2782 else {
2783 pa_tagstruct *reply;
2784 reply = reply_new(tag);
2785 pa_tagstruct_putu32(reply, idx);
2786 pa_pstream_send_tagstruct(c->pstream, reply);
2787 }
2788 }
2789
2790 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2791 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2792 uint32_t idx;
2793 playback_stream *s;
2794
2795 pa_native_connection_assert_ref(c);
2796 pa_assert(t);
2797
2798 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2799 !pa_tagstruct_eof(t)) {
2800 protocol_error(c);
2801 return;
2802 }
2803
2804 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2805 s = pa_idxset_get_by_index(c->output_streams, idx);
2806 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2807 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2808
2809 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);
2810 }
2811
2812 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2813 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2814 pa_tagstruct *reply;
2815 const pa_mempool_stat *stat;
2816
2817 pa_native_connection_assert_ref(c);
2818 pa_assert(t);
2819
2820 if (!pa_tagstruct_eof(t)) {
2821 protocol_error(c);
2822 return;
2823 }
2824
2825 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2826
2827 stat = pa_mempool_get_stat(c->protocol->core->mempool);
2828
2829 reply = reply_new(tag);
2830 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
2831 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
2832 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
2833 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
2834 pa_tagstruct_putu32(reply, (uint32_t) pa_scache_total_size(c->protocol->core));
2835 pa_pstream_send_tagstruct(c->pstream, reply);
2836 }
2837
2838 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2839 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2840 pa_tagstruct *reply;
2841 playback_stream *s;
2842 struct timeval tv, now;
2843 uint32_t idx;
2844
2845 pa_native_connection_assert_ref(c);
2846 pa_assert(t);
2847
2848 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2849 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2850 !pa_tagstruct_eof(t)) {
2851 protocol_error(c);
2852 return;
2853 }
2854
2855 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2856 s = pa_idxset_get_by_index(c->output_streams, idx);
2857 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2858 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2859
2860 /* Get an atomic snapshot of all timing parameters */
2861 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);
2862
2863 reply = reply_new(tag);
2864 pa_tagstruct_put_usec(reply,
2865 s->current_sink_latency +
2866 pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sink->sample_spec));
2867 pa_tagstruct_put_usec(reply, 0);
2868 pa_tagstruct_put_boolean(reply,
2869 s->playing_for > 0 &&
2870 pa_sink_get_state(s->sink_input->sink) == PA_SINK_RUNNING &&
2871 pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
2872 pa_tagstruct_put_timeval(reply, &tv);
2873 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2874 pa_tagstruct_puts64(reply, s->write_index);
2875 pa_tagstruct_puts64(reply, s->read_index);
2876
2877 if (c->version >= 13) {
2878 pa_tagstruct_putu64(reply, s->underrun_for);
2879 pa_tagstruct_putu64(reply, s->playing_for);
2880 }
2881
2882 pa_pstream_send_tagstruct(c->pstream, reply);
2883 }
2884
2885 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2886 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2887 pa_tagstruct *reply;
2888 record_stream *s;
2889 struct timeval tv, now;
2890 uint32_t idx;
2891
2892 pa_native_connection_assert_ref(c);
2893 pa_assert(t);
2894
2895 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2896 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2897 !pa_tagstruct_eof(t)) {
2898 protocol_error(c);
2899 return;
2900 }
2901
2902 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2903 s = pa_idxset_get_by_index(c->record_streams, idx);
2904 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2905
2906 /* Get an atomic snapshot of all timing parameters */
2907 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);
2908
2909 reply = reply_new(tag);
2910 pa_tagstruct_put_usec(reply, s->current_monitor_latency);
2911 pa_tagstruct_put_usec(reply,
2912 s->current_source_latency +
2913 pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->source->sample_spec));
2914 pa_tagstruct_put_boolean(reply,
2915 pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING &&
2916 pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING);
2917 pa_tagstruct_put_timeval(reply, &tv);
2918 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2919 pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
2920 pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
2921 pa_pstream_send_tagstruct(c->pstream, reply);
2922 }
2923
2924 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2925 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2926 upload_stream *s;
2927 uint32_t length;
2928 const char *name = NULL;
2929 pa_sample_spec ss;
2930 pa_channel_map map;
2931 pa_tagstruct *reply;
2932 pa_proplist *p;
2933
2934 pa_native_connection_assert_ref(c);
2935 pa_assert(t);
2936
2937 if (pa_tagstruct_gets(t, &name) < 0 ||
2938 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2939 pa_tagstruct_get_channel_map(t, &map) < 0 ||
2940 pa_tagstruct_getu32(t, &length) < 0) {
2941 protocol_error(c);
2942 return;
2943 }
2944
2945 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2946 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2947 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2948 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2949 CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
2950 CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
2951
2952 p = pa_proplist_new();
2953
2954 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2955 !pa_tagstruct_eof(t)) {
2956
2957 protocol_error(c);
2958 pa_proplist_free(p);
2959 return;
2960 }
2961
2962 if (c->version < 13)
2963 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2964 else if (!name)
2965 if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID)))
2966 name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME);
2967
2968 if (!name || !pa_namereg_is_valid_name(name)) {
2969 pa_proplist_free(p);
2970 CHECK_VALIDITY(c->pstream, false, tag, PA_ERR_INVALID);
2971 }
2972
2973 s = upload_stream_new(c, &ss, &map, name, length, p);
2974 pa_proplist_free(p);
2975
2976 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
2977
2978 reply = reply_new(tag);
2979 pa_tagstruct_putu32(reply, s->index);
2980 pa_tagstruct_putu32(reply, length);
2981 pa_pstream_send_tagstruct(c->pstream, reply);
2982 }
2983
2984 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2985 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2986 uint32_t channel;
2987 upload_stream *s;
2988 uint32_t idx;
2989
2990 pa_native_connection_assert_ref(c);
2991 pa_assert(t);
2992
2993 if (pa_tagstruct_getu32(t, &channel) < 0 ||
2994 !pa_tagstruct_eof(t)) {
2995 protocol_error(c);
2996 return;
2997 }
2998
2999 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3000
3001 s = pa_idxset_get_by_index(c->output_streams, channel);
3002 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3003 CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3004
3005 if (!s->memchunk.memblock)
3006 pa_pstream_send_error(c->pstream, tag, PA_ERR_TOOLARGE);
3007 else if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
3008 pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
3009 else
3010 pa_pstream_send_simple_ack(c->pstream, tag);
3011
3012 upload_stream_unlink(s);
3013 }
3014
3015 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3016 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3017 uint32_t sink_index;
3018 pa_volume_t volume;
3019 pa_sink *sink;
3020 const char *name, *sink_name;
3021 uint32_t idx;
3022 pa_proplist *p;
3023 pa_tagstruct *reply;
3024
3025 pa_native_connection_assert_ref(c);
3026 pa_assert(t);
3027
3028 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3029
3030 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
3031 pa_tagstruct_gets(t, &sink_name) < 0 ||
3032 pa_tagstruct_getu32(t, &volume) < 0 ||
3033 pa_tagstruct_gets(t, &name) < 0) {
3034 protocol_error(c);
3035 return;
3036 }
3037
3038 CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
3039 CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
3040 CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3041 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3042
3043 if (sink_index != PA_INVALID_INDEX)
3044 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
3045 else
3046 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK);
3047
3048 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
3049
3050 p = pa_proplist_new();
3051
3052 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
3053 !pa_tagstruct_eof(t)) {
3054 protocol_error(c);
3055 pa_proplist_free(p);
3056 return;
3057 }
3058
3059 pa_proplist_update(p, PA_UPDATE_MERGE, c->client->proplist);
3060
3061 if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
3062 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3063 pa_proplist_free(p);
3064 return;
3065 }
3066
3067 pa_proplist_free(p);
3068
3069 reply = reply_new(tag);
3070
3071 if (c->version >= 13)
3072 pa_tagstruct_putu32(reply, idx);
3073
3074 pa_pstream_send_tagstruct(c->pstream, reply);
3075 }
3076
3077 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3078 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3079 const char *name;
3080
3081 pa_native_connection_assert_ref(c);
3082 pa_assert(t);
3083
3084 if (pa_tagstruct_gets(t, &name) < 0 ||
3085 !pa_tagstruct_eof(t)) {
3086 protocol_error(c);
3087 return;
3088 }
3089
3090 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3091 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3092
3093 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
3094 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3095 return;
3096 }
3097
3098 pa_pstream_send_simple_ack(c->pstream, tag);
3099 }
3100
3101 static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
3102 pa_assert(c);
3103 pa_assert(fixed);
3104 pa_assert(original);
3105
3106 *fixed = *original;
3107
3108 if (c->version < 12) {
3109 /* Before protocol version 12 we didn't support S32 samples,
3110 * so we need to lie about this to the client */
3111
3112 if (fixed->format == PA_SAMPLE_S32LE)
3113 fixed->format = PA_SAMPLE_FLOAT32LE;
3114 if (fixed->format == PA_SAMPLE_S32BE)
3115 fixed->format = PA_SAMPLE_FLOAT32BE;
3116 }
3117
3118 if (c->version < 15) {
3119 if (fixed->format == PA_SAMPLE_S24LE || fixed->format == PA_SAMPLE_S24_32LE)
3120 fixed->format = PA_SAMPLE_FLOAT32LE;
3121 if (fixed->format == PA_SAMPLE_S24BE || fixed->format == PA_SAMPLE_S24_32BE)
3122 fixed->format = PA_SAMPLE_FLOAT32BE;
3123 }
3124 }
3125
3126 static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) {
3127 pa_sample_spec fixed_ss;
3128
3129 pa_assert(t);
3130 pa_sink_assert_ref(sink);
3131
3132 fixup_sample_spec(c, &fixed_ss, &sink->sample_spec);
3133
3134 pa_tagstruct_put(
3135 t,
3136 PA_TAG_U32, sink->index,
3137 PA_TAG_STRING, sink->name,
3138 PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
3139 PA_TAG_SAMPLE_SPEC, &fixed_ss,
3140 PA_TAG_CHANNEL_MAP, &sink->channel_map,
3141 PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
3142 PA_TAG_CVOLUME, pa_sink_get_volume(sink, false),
3143 PA_TAG_BOOLEAN, pa_sink_get_mute(sink, false),
3144 PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
3145 PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
3146 PA_TAG_USEC, pa_sink_get_latency(sink),
3147 PA_TAG_STRING, sink->driver,
3148 PA_TAG_U32, sink->flags & PA_SINK_CLIENT_FLAGS_MASK,
3149 PA_TAG_INVALID);
3150
3151 if (c->version >= 13) {
3152 pa_tagstruct_put_proplist(t, sink->proplist);
3153 pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
3154 }
3155
3156 if (c->version >= 15) {
3157 pa_tagstruct_put_volume(t, sink->base_volume);
3158 if (PA_UNLIKELY(pa_sink_get_state(sink) == PA_SINK_INVALID_STATE))
3159 pa_log_error("Internal sink state is invalid.");
3160 pa_tagstruct_putu32(t, pa_sink_get_state(sink));
3161 pa_tagstruct_putu32(t, sink->n_volume_steps);
3162 pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX);
3163 }
3164
3165 if (c->version >= 16) {
3166 void *state;
3167 pa_device_port *p;
3168
3169 pa_tagstruct_putu32(t, pa_hashmap_size(sink->ports));
3170
3171 PA_HASHMAP_FOREACH(p, sink->ports, state) {
3172 pa_tagstruct_puts(t, p->name);
3173 pa_tagstruct_puts(t, p->description);
3174 pa_tagstruct_putu32(t, p->priority);
3175 if (c->version >= 24)
3176 pa_tagstruct_putu32(t, p->available);
3177 }
3178
3179 pa_tagstruct_puts(t, sink->active_port ? sink->active_port->name : NULL);
3180 }
3181
3182 if (c->version >= 21) {
3183 uint32_t i;
3184 pa_format_info *f;
3185 pa_idxset *formats = pa_sink_get_formats(sink);
3186
3187 pa_tagstruct_putu8(t, (uint8_t) pa_idxset_size(formats));
3188 PA_IDXSET_FOREACH(f, formats, i) {
3189 pa_tagstruct_put_format_info(t, f);
3190 }
3191
3192 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
3193 }
3194 }
3195
3196 static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
3197 pa_sample_spec fixed_ss;
3198
3199 pa_assert(t);
3200 pa_source_assert_ref(source);
3201
3202 fixup_sample_spec(c, &fixed_ss, &source->sample_spec);
3203
3204 pa_tagstruct_put(
3205 t,
3206 PA_TAG_U32, source->index,
3207 PA_TAG_STRING, source->name,
3208 PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
3209 PA_TAG_SAMPLE_SPEC, &fixed_ss,
3210 PA_TAG_CHANNEL_MAP, &source->channel_map,
3211 PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
3212 PA_TAG_CVOLUME, pa_source_get_volume(source, false),
3213 PA_TAG_BOOLEAN, pa_source_get_mute(source, false),
3214 PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
3215 PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
3216 PA_TAG_USEC, pa_source_get_latency(source),
3217 PA_TAG_STRING, source->driver,
3218 PA_TAG_U32, source->flags & PA_SOURCE_CLIENT_FLAGS_MASK,
3219 PA_TAG_INVALID);
3220
3221 if (c->version >= 13) {
3222 pa_tagstruct_put_proplist(t, source->proplist);
3223 pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
3224 }
3225
3226 if (c->version >= 15) {
3227 pa_tagstruct_put_volume(t, source->base_volume);
3228 if (PA_UNLIKELY(pa_source_get_state(source) == PA_SOURCE_INVALID_STATE))
3229 pa_log_error("Internal source state is invalid.");
3230 pa_tagstruct_putu32(t, pa_source_get_state(source));
3231 pa_tagstruct_putu32(t, source->n_volume_steps);
3232 pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX);
3233 }
3234
3235 if (c->version >= 16) {
3236 void *state;
3237 pa_device_port *p;
3238
3239 pa_tagstruct_putu32(t, pa_hashmap_size(source->ports));
3240
3241 PA_HASHMAP_FOREACH(p, source->ports, state) {
3242 pa_tagstruct_puts(t, p->name);
3243 pa_tagstruct_puts(t, p->description);
3244 pa_tagstruct_putu32(t, p->priority);
3245 if (c->version >= 24)
3246 pa_tagstruct_putu32(t, p->available);
3247 }
3248
3249 pa_tagstruct_puts(t, source->active_port ? source->active_port->name : NULL);
3250 }
3251
3252 if (c->version >= 22) {
3253 uint32_t i;
3254 pa_format_info *f;
3255 pa_idxset *formats = pa_source_get_formats(source);
3256
3257 pa_tagstruct_putu8(t, (uint8_t) pa_idxset_size(formats));
3258 PA_IDXSET_FOREACH(f, formats, i) {
3259 pa_tagstruct_put_format_info(t, f);
3260 }
3261
3262 pa_idxset_free(formats, (pa_free_cb_t) pa_format_info_free);
3263 }
3264 }
3265
3266 static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
3267 pa_assert(t);
3268 pa_assert(client);
3269
3270 pa_tagstruct_putu32(t, client->index);
3271 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
3272 pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
3273 pa_tagstruct_puts(t, client->driver);
3274
3275 if (c->version >= 13)
3276 pa_tagstruct_put_proplist(t, client->proplist);
3277 }
3278
3279 static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
3280 void *state = NULL;
3281 pa_card_profile *p;
3282 pa_device_port *port;
3283
3284 pa_assert(t);
3285 pa_assert(card);
3286
3287 pa_tagstruct_putu32(t, card->index);
3288 pa_tagstruct_puts(t, card->name);
3289 pa_tagstruct_putu32(t, card->module ? card->module->index : PA_INVALID_INDEX);
3290 pa_tagstruct_puts(t, card->driver);
3291
3292 pa_tagstruct_putu32(t, pa_hashmap_size(card->profiles));
3293
3294 PA_HASHMAP_FOREACH(p, card->profiles, state) {
3295 pa_tagstruct_puts(t, p->name);
3296 pa_tagstruct_puts(t, p->description);
3297 pa_tagstruct_putu32(t, p->n_sinks);
3298 pa_tagstruct_putu32(t, p->n_sources);
3299 pa_tagstruct_putu32(t, p->priority);
3300
3301 if (c->version >= 29)
3302 pa_tagstruct_putu32(t, (p->available != PA_AVAILABLE_NO));
3303 }
3304
3305 pa_tagstruct_puts(t, card->active_profile->name);
3306 pa_tagstruct_put_proplist(t, card->proplist);
3307
3308 if (c->version < 26)
3309 return;
3310
3311 pa_tagstruct_putu32(t, pa_hashmap_size(card->ports));
3312
3313 PA_HASHMAP_FOREACH(port, card->ports, state) {
3314 void *state2;
3315
3316 pa_tagstruct_puts(t, port->name);
3317 pa_tagstruct_puts(t, port->description);
3318 pa_tagstruct_putu32(t, port->priority);
3319 pa_tagstruct_putu32(t, port->available);
3320 pa_tagstruct_putu8(t, port->direction);
3321 pa_tagstruct_put_proplist(t, port->proplist);
3322
3323 pa_tagstruct_putu32(t, pa_hashmap_size(port->profiles));
3324
3325 PA_HASHMAP_FOREACH(p, port->profiles, state2)
3326 pa_tagstruct_puts(t, p->name);
3327
3328 if (c->version >= 27)
3329 pa_tagstruct_puts64(t, port->latency_offset);
3330 }
3331 }
3332
3333 static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module) {
3334 pa_assert(t);
3335 pa_assert(module);
3336
3337 pa_tagstruct_putu32(t, module->index);
3338 pa_tagstruct_puts(t, module->name);
3339 pa_tagstruct_puts(t, module->argument);
3340 pa_tagstruct_putu32(t, (uint32_t) pa_module_get_n_used(module));
3341
3342 if (c->version < 15)
3343 pa_tagstruct_put_boolean(t, false); /* autoload is obsolete */
3344
3345 if (c->version >= 15)
3346 pa_tagstruct_put_proplist(t, module->proplist);
3347 }
3348
3349 static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) {
3350 pa_sample_spec fixed_ss;
3351 pa_usec_t sink_latency;
3352 pa_cvolume v;
3353 bool has_volume = false;
3354
3355 pa_assert(t);
3356 pa_sink_input_assert_ref(s);
3357
3358 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3359
3360 has_volume = pa_sink_input_is_volume_readable(s);
3361 if (has_volume)
3362 pa_sink_input_get_volume(s, &v, true);
3363 else
3364 pa_cvolume_reset(&v, fixed_ss.channels);
3365
3366 pa_tagstruct_putu32(t, s->index);
3367 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3368 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3369 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3370 pa_tagstruct_putu32(t, s->sink->index);
3371 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3372 pa_tagstruct_put_channel_map(t, &s->channel_map);
3373 pa_tagstruct_put_cvolume(t, &v);
3374 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
3375 pa_tagstruct_put_usec(t, sink_latency);
3376 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
3377 pa_tagstruct_puts(t, s->driver);
3378 if (c->version >= 11)
3379 pa_tagstruct_put_boolean(t, s->muted);
3380 if (c->version >= 13)
3381 pa_tagstruct_put_proplist(t, s->proplist);
3382 if (c->version >= 19)
3383 pa_tagstruct_put_boolean(t, (pa_sink_input_get_state(s) == PA_SINK_INPUT_CORKED));
3384 if (c->version >= 20) {
3385 pa_tagstruct_put_boolean(t, has_volume);
3386 pa_tagstruct_put_boolean(t, s->volume_writable);
3387 }
3388 if (c->version >= 21)
3389 pa_tagstruct_put_format_info(t, s->format);
3390 }
3391
3392 static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
3393 pa_sample_spec fixed_ss;
3394 pa_usec_t source_latency;
3395 pa_cvolume v;
3396 bool has_volume = false;
3397
3398 pa_assert(t);
3399 pa_source_output_assert_ref(s);
3400
3401 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3402
3403 has_volume = pa_source_output_is_volume_readable(s);
3404 if (has_volume)
3405 pa_source_output_get_volume(s, &v, true);
3406 else
3407 pa_cvolume_reset(&v, fixed_ss.channels);
3408
3409 pa_tagstruct_putu32(t, s->index);
3410 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3411 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3412 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3413 pa_tagstruct_putu32(t, s->source->index);
3414 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3415 pa_tagstruct_put_channel_map(t, &s->channel_map);
3416 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s, &source_latency));
3417 pa_tagstruct_put_usec(t, source_latency);
3418 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
3419 pa_tagstruct_puts(t, s->driver);
3420 if (c->version >= 13)
3421 pa_tagstruct_put_proplist(t, s->proplist);
3422 if (c->version >= 19)
3423 pa_tagstruct_put_boolean(t, (pa_source_output_get_state(s) == PA_SOURCE_OUTPUT_CORKED));
3424 if (c->version >= 22) {
3425 pa_tagstruct_put_cvolume(t, &v);
3426 pa_tagstruct_put_boolean(t, s->muted);
3427 pa_tagstruct_put_boolean(t, has_volume);
3428 pa_tagstruct_put_boolean(t, s->volume_writable);
3429 pa_tagstruct_put_format_info(t, s->format);
3430 }
3431 }
3432
3433 static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {
3434 pa_sample_spec fixed_ss;
3435 pa_cvolume v;
3436
3437 pa_assert(t);
3438 pa_assert(e);
3439
3440 if (e->memchunk.memblock)
3441 fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
3442 else
3443 memset(&fixed_ss, 0, sizeof(fixed_ss));
3444
3445 pa_tagstruct_putu32(t, e->index);
3446 pa_tagstruct_puts(t, e->name);
3447
3448 if (e->volume_is_set)
3449 v = e->volume;
3450 else
3451 pa_cvolume_init(&v);
3452
3453 pa_tagstruct_put_cvolume(t, &v);
3454 pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0);
3455 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3456 pa_tagstruct_put_channel_map(t, &e->channel_map);
3457 pa_tagstruct_putu32(t, (uint32_t) e->memchunk.length);
3458 pa_tagstruct_put_boolean(t, e->lazy);
3459 pa_tagstruct_puts(t, e->filename);
3460
3461 if (c->version >= 13)
3462 pa_tagstruct_put_proplist(t, e->proplist);
3463 }
3464
3465 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3466 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3467 uint32_t idx;
3468 pa_sink *sink = NULL;
3469 pa_source *source = NULL;
3470 pa_client *client = NULL;
3471 pa_card *card = NULL;
3472 pa_module *module = NULL;
3473 pa_sink_input *si = NULL;
3474 pa_source_output *so = NULL;
3475 pa_scache_entry *sce = NULL;
3476 const char *name = NULL;
3477 pa_tagstruct *reply;
3478
3479 pa_native_connection_assert_ref(c);
3480 pa_assert(t);
3481
3482 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3483 (command != PA_COMMAND_GET_CLIENT_INFO &&
3484 command != PA_COMMAND_GET_MODULE_INFO &&
3485 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
3486 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
3487 pa_tagstruct_gets(t, &name) < 0) ||
3488 !pa_tagstruct_eof(t)) {
3489 protocol_error(c);
3490 return;
3491 }
3492
3493 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3494 CHECK_VALIDITY(c->pstream, !name ||
3495 (command == PA_COMMAND_GET_SINK_INFO &&
3496 pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SINK)) ||
3497 (command == PA_COMMAND_GET_SOURCE_INFO &&
3498 pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SOURCE)) ||
3499 pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3500 CHECK_VALIDITY(c->pstream, command == PA_COMMAND_GET_SINK_INFO ||
3501 command == PA_COMMAND_GET_SOURCE_INFO ||
3502 (idx != PA_INVALID_INDEX || name), tag, PA_ERR_INVALID);
3503 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3504
3505 if (command == PA_COMMAND_GET_SINK_INFO) {
3506 if (idx != PA_INVALID_INDEX)
3507 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3508 else
3509 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3510 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
3511 if (idx != PA_INVALID_INDEX)
3512 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3513 else
3514 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3515 } else if (command == PA_COMMAND_GET_CARD_INFO) {
3516 if (idx != PA_INVALID_INDEX)
3517 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
3518 else
3519 card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
3520 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
3521 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3522 else if (command == PA_COMMAND_GET_MODULE_INFO)
3523 module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3524 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
3525 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3526 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
3527 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3528 else {
3529 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
3530 if (idx != PA_INVALID_INDEX)
3531 sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
3532 else
3533 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
3534 }
3535
3536 if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
3537 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3538 return;
3539 }
3540
3541 reply = reply_new(tag);
3542 if (sink)
3543 sink_fill_tagstruct(c, reply, sink);
3544 else if (source)
3545 source_fill_tagstruct(c, reply, source);
3546 else if (client)
3547 client_fill_tagstruct(c, reply, client);
3548 else if (card)
3549 card_fill_tagstruct(c, reply, card);
3550 else if (module)
3551 module_fill_tagstruct(c, reply, module);
3552 else if (si)
3553 sink_input_fill_tagstruct(c, reply, si);
3554 else if (so)
3555 source_output_fill_tagstruct(c, reply, so);
3556 else
3557 scache_fill_tagstruct(c, reply, sce);
3558 pa_pstream_send_tagstruct(c->pstream, reply);
3559 }
3560
3561 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3562 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3563 pa_idxset *i;
3564 uint32_t idx;
3565 void *p;
3566 pa_tagstruct *reply;
3567
3568 pa_native_connection_assert_ref(c);
3569 pa_assert(t);
3570
3571 if (!pa_tagstruct_eof(t)) {
3572 protocol_error(c);
3573 return;
3574 }
3575
3576 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3577
3578 reply = reply_new(tag);
3579
3580 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3581 i = c->protocol->core->sinks;
3582 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3583 i = c->protocol->core->sources;
3584 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3585 i = c->protocol->core->clients;
3586 else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3587 i = c->protocol->core->cards;
3588 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3589 i = c->protocol->core->modules;
3590 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3591 i = c->protocol->core->sink_inputs;
3592 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3593 i = c->protocol->core->source_outputs;
3594 else {
3595 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3596 i = c->protocol->core->scache;
3597 }
3598
3599 if (i) {
3600 PA_IDXSET_FOREACH(p, i, idx) {
3601 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3602 sink_fill_tagstruct(c, reply, p);
3603 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3604 source_fill_tagstruct(c, reply, p);
3605 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3606 client_fill_tagstruct(c, reply, p);
3607 else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3608 card_fill_tagstruct(c, reply, p);
3609 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3610 module_fill_tagstruct(c, reply, p);
3611 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3612 sink_input_fill_tagstruct(c, reply, p);
3613 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3614 source_output_fill_tagstruct(c, reply, p);
3615 else {
3616 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3617 scache_fill_tagstruct(c, reply, p);
3618 }
3619 }
3620 }
3621
3622 pa_pstream_send_tagstruct(c->pstream, reply);
3623 }
3624
3625 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3626 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3627 pa_tagstruct *reply;
3628 pa_sink *def_sink;
3629 pa_source *def_source;
3630 pa_sample_spec fixed_ss;
3631 char *h, *u;
3632
3633 pa_native_connection_assert_ref(c);
3634 pa_assert(t);
3635
3636 if (!pa_tagstruct_eof(t)) {
3637 protocol_error(c);
3638 return;
3639 }
3640
3641 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3642
3643 reply = reply_new(tag);
3644 pa_tagstruct_puts(reply, PACKAGE_NAME);
3645 pa_tagstruct_puts(reply, PACKAGE_VERSION);
3646
3647 u = pa_get_user_name_malloc();
3648 pa_tagstruct_puts(reply, u);
3649 pa_xfree(u);
3650
3651 h = pa_get_host_name_malloc();
3652 pa_tagstruct_puts(reply, h);
3653 pa_xfree(h);
3654
3655 fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
3656 pa_tagstruct_put_sample_spec(reply, &fixed_ss);
3657
3658 def_sink = pa_namereg_get_default_sink(c->protocol->core);
3659 pa_tagstruct_puts(reply, def_sink ? def_sink->name : NULL);
3660 def_source = pa_namereg_get_default_source(c->protocol->core);
3661 pa_tagstruct_puts(reply, def_source ? def_source->name : NULL);
3662
3663 pa_tagstruct_putu32(reply, c->protocol->core->cookie);
3664
3665 if (c->version >= 15)
3666 pa_tagstruct_put_channel_map(reply, &c->protocol->core->default_channel_map);
3667
3668 pa_pstream_send_tagstruct(c->pstream, reply);
3669 }
3670
3671 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
3672 pa_tagstruct *t;
3673 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3674
3675 pa_native_connection_assert_ref(c);
3676
3677 t = pa_tagstruct_new(NULL, 0);
3678 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
3679 pa_tagstruct_putu32(t, (uint32_t) -1);
3680 pa_tagstruct_putu32(t, e);
3681 pa_tagstruct_putu32(t, idx);
3682 pa_pstream_send_tagstruct(c->pstream, t);
3683 }
3684
3685 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3686 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3687 pa_subscription_mask_t m;
3688
3689 pa_native_connection_assert_ref(c);
3690 pa_assert(t);
3691
3692 if (pa_tagstruct_getu32(t, &m) < 0 ||
3693 !pa_tagstruct_eof(t)) {
3694 protocol_error(c);
3695 return;
3696 }
3697
3698 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3699 CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
3700
3701 if (c->subscription)
3702 pa_subscription_free(c->subscription);
3703
3704 if (m != 0) {
3705 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
3706 pa_assert(c->subscription);
3707 } else
3708 c->subscription = NULL;
3709
3710 pa_pstream_send_simple_ack(c->pstream, tag);
3711 }
3712
3713 static void command_set_volume(
3714 pa_pdispatch *pd,
3715 uint32_t command,
3716 uint32_t tag,
3717 pa_tagstruct *t,
3718 void *userdata) {
3719
3720 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3721 uint32_t idx;
3722 pa_cvolume volume;
3723 pa_sink *sink = NULL;
3724 pa_source *source = NULL;
3725 pa_sink_input *si = NULL;
3726 pa_source_output *so = NULL;
3727 const char *name = NULL;
3728 const char *client_name;
3729
3730 pa_native_connection_assert_ref(c);
3731 pa_assert(t);
3732
3733 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3734 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3735 (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3736 pa_tagstruct_get_cvolume(t, &volume) ||
3737 !pa_tagstruct_eof(t)) {
3738 protocol_error(c);
3739 return;
3740 }
3741
3742 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3743 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);
3744 CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
3745 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
3746
3747 switch (command) {
3748
3749 case PA_COMMAND_SET_SINK_VOLUME:
3750 if (idx != PA_INVALID_INDEX)
3751 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3752 else
3753 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3754 break;
3755
3756 case PA_COMMAND_SET_SOURCE_VOLUME:
3757 if (idx != PA_INVALID_INDEX)
3758 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3759 else
3760 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3761 break;
3762
3763 case PA_COMMAND_SET_SINK_INPUT_VOLUME:
3764 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3765 break;
3766
3767 case PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME:
3768 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3769 break;
3770
3771 default:
3772 pa_assert_not_reached();
3773 }
3774
3775 CHECK_VALIDITY(c->pstream, si || so || sink || source, tag, PA_ERR_NOENTITY);
3776
3777 client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3778
3779 if (sink) {
3780 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &sink->sample_spec), tag, PA_ERR_INVALID);
3781
3782 pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
3783 pa_sink_set_volume(sink, &volume, true, true);
3784 } else if (source) {
3785 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &source->sample_spec), tag, PA_ERR_INVALID);
3786
3787 pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
3788 pa_source_set_volume(source, &volume, true, true);
3789 } else if (si) {
3790 CHECK_VALIDITY(c->pstream, si->volume_writable, tag, PA_ERR_BADSTATE);
3791 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &si->sample_spec), tag, PA_ERR_INVALID);
3792
3793 pa_log_debug("Client %s changes volume of sink input %s.",
3794 client_name,
3795 pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3796 pa_sink_input_set_volume(si, &volume, true, true);
3797 } else if (so) {
3798 CHECK_VALIDITY(c->pstream, so->volume_writable, tag, PA_ERR_BADSTATE);
3799 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &so->sample_spec), tag, PA_ERR_INVALID);
3800
3801 pa_log_debug("Client %s changes volume of source output %s.",
3802 client_name,
3803 pa_strnull(pa_proplist_gets(so->proplist, PA_PROP_MEDIA_NAME)));
3804 pa_source_output_set_volume(so, &volume, true, true);
3805 }
3806
3807 pa_pstream_send_simple_ack(c->pstream, tag);
3808 }
3809
3810 static void command_set_mute(
3811 pa_pdispatch *pd,
3812 uint32_t command,
3813 uint32_t tag,
3814 pa_tagstruct *t,
3815 void *userdata) {
3816
3817 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3818 uint32_t idx;
3819 bool mute;
3820 pa_sink *sink = NULL;
3821 pa_source *source = NULL;
3822 pa_sink_input *si = NULL;
3823 pa_source_output *so = NULL;
3824 const char *name = NULL, *client_name;
3825
3826 pa_native_connection_assert_ref(c);
3827 pa_assert(t);
3828
3829 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3830 (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3831 (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3832 pa_tagstruct_get_boolean(t, &mute) ||
3833 !pa_tagstruct_eof(t)) {
3834 protocol_error(c);
3835 return;
3836 }
3837
3838 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3839 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);
3840 CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
3841
3842 switch (command) {
3843
3844 case PA_COMMAND_SET_SINK_MUTE:
3845 if (idx != PA_INVALID_INDEX)
3846 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3847 else
3848 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3849
3850 break;
3851
3852 case PA_COMMAND_SET_SOURCE_MUTE:
3853 if (idx != PA_INVALID_INDEX)
3854 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3855 else
3856 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3857
3858 break;
3859
3860 case PA_COMMAND_SET_SINK_INPUT_MUTE:
3861 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3862 break;
3863
3864 case PA_COMMAND_SET_SOURCE_OUTPUT_MUTE:
3865 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3866 break;
3867
3868 default:
3869 pa_assert_not_reached();
3870 }
3871
3872 CHECK_VALIDITY(c->pstream, si || so || sink || source, tag, PA_ERR_NOENTITY);
3873
3874 client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3875
3876 if (sink) {
3877 pa_log_debug("Client %s changes mute of sink %s.", client_name, sink->name);
3878 pa_sink_set_mute(sink, mute, true);
3879 } else if (source) {
3880 pa_log_debug("Client %s changes mute of source %s.", client_name, source->name);
3881 pa_source_set_mute(source, mute, true);
3882 } else if (si) {
3883 pa_log_debug("Client %s changes mute of sink input %s.",
3884 client_name,
3885 pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3886 pa_sink_input_set_mute(si, mute, true);
3887 } else if (so) {
3888 pa_log_debug("Client %s changes mute of source output %s.",
3889 client_name,
3890 pa_strnull(pa_proplist_gets(so->proplist, PA_PROP_MEDIA_NAME)));
3891 pa_source_output_set_mute(so, mute, true);
3892 }
3893
3894 pa_pstream_send_simple_ack(c->pstream, tag);
3895 }
3896
3897 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3898 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3899 uint32_t idx;
3900 bool b;
3901 playback_stream *s;
3902
3903 pa_native_connection_assert_ref(c);
3904 pa_assert(t);
3905
3906 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3907 pa_tagstruct_get_boolean(t, &b) < 0 ||
3908 !pa_tagstruct_eof(t)) {
3909 protocol_error(c);
3910 return;
3911 }
3912
3913 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3914 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3915 s = pa_idxset_get_by_index(c->output_streams, idx);
3916 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3917 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3918
3919 pa_sink_input_cork(s->sink_input, b);
3920
3921 if (b)
3922 s->is_underrun = true;
3923
3924 pa_pstream_send_simple_ack(c->pstream, tag);
3925 }
3926
3927 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3928 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3929 uint32_t idx;
3930 playback_stream *s;
3931
3932 pa_native_connection_assert_ref(c);
3933 pa_assert(t);
3934
3935 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3936 !pa_tagstruct_eof(t)) {
3937 protocol_error(c);
3938 return;
3939 }
3940
3941 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3942 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3943 s = pa_idxset_get_by_index(c->output_streams, idx);
3944 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3945 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3946
3947 switch (command) {
3948 case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
3949 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
3950 break;
3951
3952 case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
3953 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
3954 break;
3955
3956 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
3957 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
3958 break;
3959
3960 default:
3961 pa_assert_not_reached();
3962 }
3963
3964 pa_pstream_send_simple_ack(c->pstream, tag);
3965 }
3966
3967 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3968 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3969 uint32_t idx;
3970 record_stream *s;
3971 bool b;
3972
3973 pa_native_connection_assert_ref(c);
3974 pa_assert(t);
3975
3976 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3977 pa_tagstruct_get_boolean(t, &b) < 0 ||
3978 !pa_tagstruct_eof(t)) {
3979 protocol_error(c);
3980 return;
3981 }
3982
3983 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3984 s = pa_idxset_get_by_index(c->record_streams, idx);
3985 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3986
3987 pa_source_output_cork(s->source_output, b);
3988 pa_memblockq_prebuf_force(s->memblockq);
3989 pa_pstream_send_simple_ack(c->pstream, tag);
3990 }
3991
3992 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3993 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3994 uint32_t idx;
3995 record_stream *s;
3996
3997 pa_native_connection_assert_ref(c);
3998 pa_assert(t);
3999
4000 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4001 !pa_tagstruct_eof(t)) {
4002 protocol_error(c);
4003 return;
4004 }
4005
4006 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4007 s = pa_idxset_get_by_index(c->record_streams, idx);
4008 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4009
4010 pa_memblockq_flush_read(s->memblockq);
4011 pa_pstream_send_simple_ack(c->pstream, tag);
4012 }
4013
4014 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4015 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4016 uint32_t idx;
4017 pa_buffer_attr a;
4018 pa_tagstruct *reply;
4019
4020 pa_native_connection_assert_ref(c);
4021 pa_assert(t);
4022
4023 memset(&a, 0, sizeof(a));
4024
4025 if (pa_tagstruct_getu32(t, &idx) < 0) {
4026 protocol_error(c);
4027 return;
4028 }
4029
4030 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4031
4032 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
4033 playback_stream *s;
4034 bool adjust_latency = false, early_requests = false;
4035
4036 s = pa_idxset_get_by_index(c->output_streams, idx);
4037 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4038 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4039
4040 if (pa_tagstruct_get(
4041 t,
4042 PA_TAG_U32, &a.maxlength,
4043 PA_TAG_U32, &a.tlength,
4044 PA_TAG_U32, &a.prebuf,
4045 PA_TAG_U32, &a.minreq,
4046 PA_TAG_INVALID) < 0 ||
4047 (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
4048 (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
4049 !pa_tagstruct_eof(t)) {
4050 protocol_error(c);
4051 return;
4052 }
4053
4054 s->adjust_latency = adjust_latency;
4055 s->early_requests = early_requests;
4056 s->buffer_attr_req = a;
4057
4058 fix_playback_buffer_attr(s);
4059 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);
4060
4061 reply = reply_new(tag);
4062 pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
4063 pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
4064 pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
4065 pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
4066
4067 if (c->version >= 13)
4068 pa_tagstruct_put_usec(reply, s->configured_sink_latency);
4069
4070 } else {
4071 record_stream *s;
4072 bool adjust_latency = false, early_requests = false;
4073 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
4074
4075 s = pa_idxset_get_by_index(c->record_streams, idx);
4076 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4077
4078 if (pa_tagstruct_get(
4079 t,
4080 PA_TAG_U32, &a.maxlength,
4081 PA_TAG_U32, &a.fragsize,
4082 PA_TAG_INVALID) < 0 ||
4083 (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
4084 (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
4085 !pa_tagstruct_eof(t)) {
4086 protocol_error(c);
4087 return;
4088 }
4089
4090 s->adjust_latency = adjust_latency;
4091 s->early_requests = early_requests;
4092 s->buffer_attr_req = a;
4093
4094 fix_record_buffer_attr_pre(s);
4095 pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
4096 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
4097 fix_record_buffer_attr_post(s);
4098
4099 reply = reply_new(tag);
4100 pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
4101 pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
4102
4103 if (c->version >= 13)
4104 pa_tagstruct_put_usec(reply, s->configured_source_latency);
4105 }
4106
4107 pa_pstream_send_tagstruct(c->pstream, reply);
4108 }
4109
4110 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4111 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4112 uint32_t idx;
4113 uint32_t rate;
4114
4115 pa_native_connection_assert_ref(c);
4116 pa_assert(t);
4117
4118 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4119 pa_tagstruct_getu32(t, &rate) < 0 ||
4120 !pa_tagstruct_eof(t)) {
4121 protocol_error(c);
4122 return;
4123 }
4124
4125 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4126 CHECK_VALIDITY(c->pstream, pa_sample_rate_valid(rate), tag, PA_ERR_INVALID);
4127
4128 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
4129 playback_stream *s;
4130
4131 s = pa_idxset_get_by_index(c->output_streams, idx);
4132 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4133 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4134
4135 pa_sink_input_set_rate(s->sink_input, rate);
4136
4137 } else {
4138 record_stream *s;
4139 pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
4140
4141 s = pa_idxset_get_by_index(c->record_streams, idx);
4142 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4143
4144 pa_source_output_set_rate(s->source_output, rate);
4145 }
4146
4147 pa_pstream_send_simple_ack(c->pstream, tag);
4148 }
4149
4150 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4151 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4152 uint32_t idx;
4153 uint32_t mode;
4154 pa_proplist *p;
4155
4156 pa_native_connection_assert_ref(c);
4157 pa_assert(t);
4158
4159 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4160
4161 p = pa_proplist_new();
4162
4163 if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
4164
4165 if (pa_tagstruct_getu32(t, &mode) < 0 ||
4166 pa_tagstruct_get_proplist(t, p) < 0 ||
4167 !pa_tagstruct_eof(t)) {
4168 protocol_error(c);
4169 pa_proplist_free(p);
4170 return;
4171 }
4172
4173 } else {
4174
4175 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4176 pa_tagstruct_getu32(t, &mode) < 0 ||
4177 pa_tagstruct_get_proplist(t, p) < 0 ||
4178 !pa_tagstruct_eof(t)) {
4179 protocol_error(c);
4180 pa_proplist_free(p);
4181 return;
4182 }
4183 }
4184
4185 if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) {
4186 pa_proplist_free(p);
4187 CHECK_VALIDITY(c->pstream, false, tag, PA_ERR_INVALID);
4188 }
4189
4190 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
4191 playback_stream *s;
4192
4193 s = pa_idxset_get_by_index(c->output_streams, idx);
4194 if (!s || !playback_stream_isinstance(s)) {
4195 pa_proplist_free(p);
4196 CHECK_VALIDITY(c->pstream, false, tag, PA_ERR_NOENTITY);
4197 }
4198 pa_sink_input_update_proplist(s->sink_input, mode, p);
4199
4200 } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
4201 record_stream *s;
4202
4203 if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
4204 pa_proplist_free(p);
4205 CHECK_VALIDITY(c->pstream, false, tag, PA_ERR_NOENTITY);
4206 }
4207 pa_source_output_update_proplist(s->source_output, mode, p);
4208
4209 } else {
4210 pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
4211
4212 pa_client_update_proplist(c->client, mode, p);
4213 }
4214
4215 pa_pstream_send_simple_ack(c->pstream, tag);
4216 pa_proplist_free(p);
4217 }
4218
4219 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4220 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4221 uint32_t idx;
4222 unsigned changed = 0;
4223 pa_proplist *p;
4224 pa_strlist *l = NULL;
4225
4226 pa_native_connection_assert_ref(c);
4227 pa_assert(t);
4228
4229 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4230
4231 if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
4232
4233 if (pa_tagstruct_getu32(t, &idx) < 0) {
4234 protocol_error(c);
4235 return;
4236 }
4237 }
4238
4239 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
4240 playback_stream *s;
4241
4242 s = pa_idxset_get_by_index(c->output_streams, idx);
4243 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4244 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4245
4246 p = s->sink_input->proplist;
4247
4248 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
4249 record_stream *s;
4250
4251 s = pa_idxset_get_by_index(c->record_streams, idx);
4252 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4253
4254 p = s->source_output->proplist;
4255 } else {
4256 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
4257
4258 p = c->client->proplist;
4259 }
4260
4261 for (;;) {
4262 const char *k;
4263
4264 if (pa_tagstruct_gets(t, &k) < 0) {
4265 protocol_error(c);
4266 pa_strlist_free(l);
4267 return;
4268 }
4269
4270 if (!k)
4271 break;
4272
4273 l = pa_strlist_prepend(l, k);
4274 }
4275
4276 if (!pa_tagstruct_eof(t)) {
4277 protocol_error(c);
4278 pa_strlist_free(l);
4279 return;
4280 }
4281
4282 for (;;) {
4283 char *z;
4284
4285 l = pa_strlist_pop(l, &z);
4286
4287 if (!z)
4288 break;
4289
4290 changed += (unsigned) (pa_proplist_unset(p, z) >= 0);
4291 pa_xfree(z);
4292 }
4293
4294 pa_pstream_send_simple_ack(c->pstream, tag);
4295
4296 if (changed) {
4297 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
4298 playback_stream *s;
4299
4300 s = pa_idxset_get_by_index(c->output_streams, idx);
4301 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
4302
4303 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
4304 record_stream *s;
4305
4306 s = pa_idxset_get_by_index(c->record_streams, idx);
4307 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
4308
4309 } else {
4310 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
4311 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
4312 }
4313 }
4314 }
4315
4316 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4317 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4318 const char *s;
4319
4320 pa_native_connection_assert_ref(c);
4321 pa_assert(t);
4322
4323 if (pa_tagstruct_gets(t, &s) < 0 ||
4324 !pa_tagstruct_eof(t)) {
4325 protocol_error(c);
4326 return;
4327 }
4328
4329 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4330 CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID);
4331
4332 if (command == PA_COMMAND_SET_DEFAULT_SOURCE) {
4333 pa_source *source;
4334
4335 source = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SOURCE);
4336 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4337
4338 pa_namereg_set_default_source(c->protocol->core, source);
4339 } else {
4340 pa_sink *sink;
4341 pa_assert(command == PA_COMMAND_SET_DEFAULT_SINK);
4342
4343 sink = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SINK);
4344 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4345
4346 pa_namereg_set_default_sink(c->protocol->core, sink);
4347 }
4348
4349 pa_pstream_send_simple_ack(c->pstream, tag);
4350 }
4351
4352 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4353 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4354 uint32_t idx;
4355 const char *name;
4356
4357 pa_native_connection_assert_ref(c);
4358 pa_assert(t);
4359
4360 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4361 pa_tagstruct_gets(t, &name) < 0 ||
4362 !pa_tagstruct_eof(t)) {
4363 protocol_error(c);
4364 return;
4365 }
4366
4367 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4368 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
4369
4370 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
4371 playback_stream *s;
4372
4373 s = pa_idxset_get_by_index(c->output_streams, idx);
4374 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4375 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4376
4377 pa_sink_input_set_name(s->sink_input, name);
4378
4379 } else {
4380 record_stream *s;
4381 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
4382
4383 s = pa_idxset_get_by_index(c->record_streams, idx);
4384 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4385
4386 pa_source_output_set_name(s->source_output, name);
4387 }
4388
4389 pa_pstream_send_simple_ack(c->pstream, tag);
4390 }
4391
4392 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4393 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4394 uint32_t idx;
4395
4396 pa_native_connection_assert_ref(c);
4397 pa_assert(t);
4398
4399 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4400 !pa_tagstruct_eof(t)) {
4401 protocol_error(c);
4402 return;
4403 }
4404
4405 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4406
4407 if (command == PA_COMMAND_KILL_CLIENT) {
4408 pa_client *client;
4409
4410 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
4411 CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
4412
4413 pa_native_connection_ref(c);
4414 pa_client_kill(client);
4415
4416 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
4417 pa_sink_input *s;
4418
4419 s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4420 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4421
4422 pa_native_connection_ref(c);
4423 pa_sink_input_kill(s);
4424 } else {
4425 pa_source_output *s;
4426
4427 pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
4428
4429 s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4430 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4431
4432 pa_native_connection_ref(c);
4433 pa_source_output_kill(s);
4434 }
4435
4436 pa_pstream_send_simple_ack(c->pstream, tag);
4437 pa_native_connection_unref(c);
4438 }
4439
4440 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4441 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4442 pa_module *m;
4443 const char *name, *argument;
4444 pa_tagstruct *reply;
4445
4446 pa_native_connection_assert_ref(c);
4447 pa_assert(t);
4448
4449 if (pa_tagstruct_gets(t, &name) < 0 ||
4450 pa_tagstruct_gets(t, &argument) < 0 ||
4451 !pa_tagstruct_eof(t)) {
4452 protocol_error(c);
4453 return;
4454 }
4455
4456 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4457 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
4458 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
4459
4460 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
4461 pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
4462 return;
4463 }
4464
4465 reply = reply_new(tag);
4466 pa_tagstruct_putu32(reply, m->index);
4467 pa_pstream_send_tagstruct(c->pstream, reply);
4468 }
4469
4470 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4471 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4472 uint32_t idx;
4473 pa_module *m;
4474
4475 pa_native_connection_assert_ref(c);
4476 pa_assert(t);
4477
4478 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4479 !pa_tagstruct_eof(t)) {
4480 protocol_error(c);
4481 return;
4482 }
4483
4484 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4485 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4486 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
4487
4488 pa_module_unload_request(m, false);
4489 pa_pstream_send_simple_ack(c->pstream, tag);
4490 }
4491
4492 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4493 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4494 uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
4495 const char *name_device = NULL;
4496
4497 pa_native_connection_assert_ref(c);
4498 pa_assert(t);
4499
4500 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4501 pa_tagstruct_getu32(t, &idx_device) < 0 ||
4502 pa_tagstruct_gets(t, &name_device) < 0 ||
4503 !pa_tagstruct_eof(t)) {
4504 protocol_error(c);
4505 return;
4506 }
4507
4508 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4509 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4510
4511 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);
4512 CHECK_VALIDITY(c->pstream, (idx_device != PA_INVALID_INDEX) ^ (name_device != NULL), tag, PA_ERR_INVALID);
4513
4514 if (command == PA_COMMAND_MOVE_SINK_INPUT) {
4515 pa_sink_input *si = NULL;
4516 pa_sink *sink = NULL;
4517
4518 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4519
4520 if (idx_device != PA_INVALID_INDEX)
4521 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
4522 else
4523 sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK);
4524
4525 CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
4526
4527 if (pa_sink_input_move_to(si, sink, true) < 0) {
4528 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4529 return;
4530 }
4531 } else {
4532 pa_source_output *so = NULL;
4533 pa_source *source;
4534
4535 pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
4536
4537 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4538
4539 if (idx_device != PA_INVALID_INDEX)
4540 source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
4541 else
4542 source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE);
4543
4544 CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
4545
4546 if (pa_source_output_move_to(so, source, true) < 0) {
4547 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4548 return;
4549 }
4550 }
4551
4552 pa_pstream_send_simple_ack(c->pstream, tag);
4553 }
4554
4555 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4556 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4557 uint32_t idx = PA_INVALID_INDEX;
4558 const char *name = NULL;
4559 bool b;
4560
4561 pa_native_connection_assert_ref(c);
4562 pa_assert(t);
4563
4564 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4565 pa_tagstruct_gets(t, &name) < 0 ||
4566 pa_tagstruct_get_boolean(t, &b) < 0 ||
4567 !pa_tagstruct_eof(t)) {
4568 protocol_error(c);
4569 return;
4570 }
4571
4572 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4573 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);
4574 CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
4575
4576 if (command == PA_COMMAND_SUSPEND_SINK) {
4577
4578 if (idx == PA_INVALID_INDEX && name && !*name) {
4579
4580 pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
4581
4582 if (pa_sink_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4583 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4584 return;
4585 }
4586 } else {
4587 pa_sink *sink = NULL;
4588
4589 if (idx != PA_INVALID_INDEX)
4590 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4591 else
4592 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4593
4594 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4595
4596 pa_log_debug("%s of sink %s requested by client %" PRIu32 ".",
4597 b ? "Suspending" : "Resuming", sink->name, c->client->index);
4598
4599 if (pa_sink_suspend(sink, b, PA_SUSPEND_USER) < 0) {
4600 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4601 return;
4602 }
4603 }
4604 } else {
4605
4606 pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
4607
4608 if (idx == PA_INVALID_INDEX && name && !*name) {
4609
4610 pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
4611
4612 if (pa_source_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4613 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4614 return;
4615 }
4616
4617 } else {
4618 pa_source *source;
4619
4620 if (idx != PA_INVALID_INDEX)
4621 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4622 else
4623 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4624
4625 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4626
4627 pa_log_debug("%s of source %s requested by client %" PRIu32 ".",
4628 b ? "Suspending" : "Resuming", source->name, c->client->index);
4629
4630 if (pa_source_suspend(source, b, PA_SUSPEND_USER) < 0) {
4631 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4632 return;
4633 }
4634 }
4635 }
4636
4637 pa_pstream_send_simple_ack(c->pstream, tag);
4638 }
4639
4640 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4641 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4642 uint32_t idx = PA_INVALID_INDEX;
4643 const char *name = NULL;
4644 pa_module *m;
4645 pa_native_protocol_ext_cb_t cb;
4646
4647 pa_native_connection_assert_ref(c);
4648 pa_assert(t);
4649
4650 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4651 pa_tagstruct_gets(t, &name) < 0) {
4652 protocol_error(c);
4653 return;
4654 }
4655
4656 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4657 CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
4658 CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
4659
4660 if (idx != PA_INVALID_INDEX)
4661 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4662 else
4663 PA_IDXSET_FOREACH(m, c->protocol->core->modules, idx)
4664 if (pa_streq(name, m->name))
4665 break;
4666
4667 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
4668 CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4669
4670 cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m);
4671 CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION);
4672
4673 if (cb(c->protocol, m, c, tag, t) < 0)
4674 protocol_error(c);
4675 }
4676
4677 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4678 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4679 uint32_t idx = PA_INVALID_INDEX;
4680 const char *name = NULL, *profile_name = NULL;
4681 pa_card *card = NULL;
4682 pa_card_profile *profile;
4683 int ret;
4684
4685 pa_native_connection_assert_ref(c);
4686 pa_assert(t);
4687
4688 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4689 pa_tagstruct_gets(t, &name) < 0 ||
4690 pa_tagstruct_gets(t, &profile_name) < 0 ||
4691 !pa_tagstruct_eof(t)) {
4692 protocol_error(c);
4693 return;
4694 }
4695
4696 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4697 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4698 CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
4699 CHECK_VALIDITY(c->pstream, profile_name, tag, PA_ERR_INVALID);
4700
4701 if (idx != PA_INVALID_INDEX)
4702 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4703 else
4704 card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
4705
4706 CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4707
4708 profile = pa_hashmap_get(card->profiles, profile_name);
4709
4710 CHECK_VALIDITY(c->pstream, profile, tag, PA_ERR_NOENTITY);
4711
4712 if ((ret = pa_card_set_profile(card, profile, true)) < 0) {
4713 pa_pstream_send_error(c->pstream, tag, -ret);
4714 return;
4715 }
4716
4717 pa_pstream_send_simple_ack(c->pstream, tag);
4718 }
4719
4720 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4721 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4722 uint32_t idx = PA_INVALID_INDEX;
4723 const char *name = NULL, *port = NULL;
4724 int ret;
4725
4726 pa_native_connection_assert_ref(c);
4727 pa_assert(t);
4728
4729 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4730 pa_tagstruct_gets(t, &name) < 0 ||
4731 pa_tagstruct_gets(t, &port) < 0 ||
4732 !pa_tagstruct_eof(t)) {
4733 protocol_error(c);
4734 return;
4735 }
4736
4737 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4738 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);
4739 CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (name != NULL), tag, PA_ERR_INVALID);
4740 CHECK_VALIDITY(c->pstream, port, tag, PA_ERR_INVALID);
4741
4742 if (command == PA_COMMAND_SET_SINK_PORT) {
4743 pa_sink *sink;
4744
4745 if (idx != PA_INVALID_INDEX)
4746 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4747 else
4748 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4749
4750 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4751
4752 if ((ret = pa_sink_set_port(sink, port, true)) < 0) {
4753 pa_pstream_send_error(c->pstream, tag, -ret);
4754 return;
4755 }
4756 } else {
4757 pa_source *source;
4758
4759 pa_assert(command == PA_COMMAND_SET_SOURCE_PORT);
4760
4761 if (idx != PA_INVALID_INDEX)
4762 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4763 else
4764 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4765
4766 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4767
4768 if ((ret = pa_source_set_port(source, port, true)) < 0) {
4769 pa_pstream_send_error(c->pstream, tag, -ret);
4770 return;
4771 }
4772 }
4773
4774 pa_pstream_send_simple_ack(c->pstream, tag);
4775 }
4776
4777 static void command_set_port_latency_offset(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4778 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4779 const char *port_name, *card_name;
4780 uint32_t idx = PA_INVALID_INDEX;
4781 int64_t offset;
4782 pa_card *card = NULL;
4783 pa_device_port *port = NULL;
4784
4785 pa_native_connection_assert_ref(c);
4786 pa_assert(t);
4787
4788 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4789 pa_tagstruct_gets(t, &card_name) < 0 ||
4790 pa_tagstruct_gets(t, &port_name) < 0 ||
4791 pa_tagstruct_gets64(t, &offset) < 0 ||
4792 !pa_tagstruct_eof(t)) {
4793 protocol_error(c);
4794 return;
4795 }
4796
4797 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4798 CHECK_VALIDITY(c->pstream, !card_name || pa_namereg_is_valid_name(card_name), tag, PA_ERR_INVALID);
4799 CHECK_VALIDITY(c->pstream, (idx != PA_INVALID_INDEX) ^ (card_name != NULL), tag, PA_ERR_INVALID);
4800 CHECK_VALIDITY(c->pstream, port_name, tag, PA_ERR_INVALID);
4801
4802 if (idx != PA_INVALID_INDEX)
4803 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4804 else
4805 card = pa_namereg_get(c->protocol->core, card_name, PA_NAMEREG_CARD);
4806
4807 CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4808
4809 port = pa_hashmap_get(card->ports, port_name);
4810 CHECK_VALIDITY(c->pstream, port, tag, PA_ERR_NOENTITY);
4811
4812 pa_device_port_set_latency_offset(port, offset);
4813
4814 pa_pstream_send_simple_ack(c->pstream, tag);
4815 }
4816
4817 /*** pstream callbacks ***/
4818
4819 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
4820 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4821
4822 pa_assert(p);
4823 pa_assert(packet);
4824 pa_native_connection_assert_ref(c);
4825
4826 if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
4827 pa_log("invalid packet.");
4828 native_connection_unlink(c);
4829 }
4830 }
4831
4832 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) {
4833 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4834 output_stream *stream;
4835
4836 pa_assert(p);
4837 pa_assert(chunk);
4838 pa_native_connection_assert_ref(c);
4839
4840 if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
4841 pa_log_debug("Client sent block for invalid stream.");
4842 /* Ignoring */
4843 return;
4844 }
4845
4846 #ifdef PROTOCOL_NATIVE_DEBUG
4847 pa_log("got %lu bytes from client", (unsigned long) chunk->length);
4848 #endif
4849
4850 if (playback_stream_isinstance(stream)) {
4851 playback_stream *ps = PLAYBACK_STREAM(stream);
4852
4853 pa_atomic_inc(&ps->seek_or_post_in_queue);
4854 if (chunk->memblock) {
4855 if (seek != PA_SEEK_RELATIVE || offset != 0)
4856 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);
4857 else
4858 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
4859 } else
4860 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);
4861
4862 } else {
4863 upload_stream *u = UPLOAD_STREAM(stream);
4864 size_t l;
4865
4866 if (!u->memchunk.memblock) {
4867 if (u->length == chunk->length && chunk->memblock) {
4868 u->memchunk = *chunk;
4869 pa_memblock_ref(u->memchunk.memblock);
4870 u->length = 0;
4871 } else {
4872 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
4873 u->memchunk.index = u->memchunk.length = 0;
4874 }
4875 }
4876
4877 pa_assert(u->memchunk.memblock);
4878
4879 l = u->length;
4880 if (l > chunk->length)
4881 l = chunk->length;
4882
4883 if (l > 0) {
4884 void *dst;
4885 dst = pa_memblock_acquire(u->memchunk.memblock);
4886
4887 if (chunk->memblock) {
4888 void *src;
4889 src = pa_memblock_acquire(chunk->memblock);
4890
4891 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
4892 (uint8_t*) src + chunk->index, l);
4893
4894 pa_memblock_release(chunk->memblock);
4895 } else
4896 pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec);
4897
4898 pa_memblock_release(u->memchunk.memblock);
4899
4900 u->memchunk.length += l;
4901 u->length -= l;
4902 }
4903 }
4904 }
4905
4906 static void pstream_die_callback(pa_pstream *p, void *userdata) {
4907 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4908
4909 pa_assert(p);
4910 pa_native_connection_assert_ref(c);
4911
4912 native_connection_unlink(c);
4913 pa_log_info("Connection died.");
4914 }
4915
4916 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
4917 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4918
4919 pa_assert(p);
4920 pa_native_connection_assert_ref(c);
4921
4922 native_connection_send_memblock(c);
4923 }
4924
4925 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4926 pa_thread_mq *q;
4927
4928 if (!(q = pa_thread_mq_get()))
4929 pa_pstream_send_revoke(p, block_id);
4930 else
4931 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4932 }
4933
4934 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4935 pa_thread_mq *q;
4936
4937 if (!(q = pa_thread_mq_get()))
4938 pa_pstream_send_release(p, block_id);
4939 else
4940 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4941 }
4942
4943 /*** client callbacks ***/
4944
4945 static void client_kill_cb(pa_client *c) {
4946 pa_assert(c);
4947
4948 native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
4949 pa_log_info("Connection killed.");
4950 }
4951
4952 static void client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl) {
4953 pa_tagstruct *t;
4954 pa_native_connection *c;
4955
4956 pa_assert(client);
4957 c = PA_NATIVE_CONNECTION(client->userdata);
4958 pa_native_connection_assert_ref(c);
4959
4960 if (c->version < 15)
4961 return;
4962
4963 t = pa_tagstruct_new(NULL, 0);
4964 pa_tagstruct_putu32(t, PA_COMMAND_CLIENT_EVENT);
4965 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
4966 pa_tagstruct_puts(t, event);
4967 pa_tagstruct_put_proplist(t, pl);
4968 pa_pstream_send_tagstruct(c->pstream, t);
4969 }
4970
4971 /*** module entry points ***/
4972
4973 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) {
4974 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4975
4976 pa_assert(m);
4977 pa_native_connection_assert_ref(c);
4978 pa_assert(c->auth_timeout_event == e);
4979
4980 if (!c->authorized) {
4981 native_connection_unlink(c);
4982 pa_log_info("Connection terminated due to authentication timeout.");
4983 }
4984 }
4985
4986 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
4987 pa_native_connection *c;
4988 char pname[128];
4989 pa_client *client;
4990 pa_client_new_data data;
4991
4992 pa_assert(p);
4993 pa_assert(io);
4994 pa_assert(o);
4995
4996 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
4997 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
4998 pa_iochannel_free(io);
4999 return;
5000 }
5001
5002 pa_client_new_data_init(&data);
5003 data.module = o->module;
5004 data.driver = __FILE__;
5005 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
5006 pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname);
5007 pa_proplist_sets(data.proplist, "native-protocol.peer", pname);
5008 client = pa_client_new(p->core, &data);
5009 pa_client_new_data_done(&data);
5010
5011 if (!client)
5012 return;
5013
5014 c = pa_msgobject_new(pa_native_connection);
5015 c->parent.parent.free = native_connection_free;
5016 c->parent.process_msg = native_connection_process_msg;
5017 c->protocol = p;
5018 c->options = pa_native_options_ref(o);
5019 c->authorized = false;
5020
5021 if (o->auth_anonymous) {
5022 pa_log_info("Client authenticated anonymously.");
5023 c->authorized = true;
5024 }
5025
5026 if (!c->authorized &&
5027 o->auth_ip_acl &&
5028 pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
5029
5030 pa_log_info("Client authenticated by IP ACL.");
5031 c->authorized = true;
5032 }
5033
5034 if (!c->authorized)
5035 c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
5036 else
5037 c->auth_timeout_event = NULL;
5038
5039 c->is_local = pa_iochannel_socket_is_local(io);
5040 c->version = 8;
5041
5042 c->client = client;
5043 c->client->kill = client_kill_cb;
5044 c->client->send_event = client_send_event_cb;
5045 c->client->userdata = c;
5046
5047 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
5048 pa_pstream_set_receive_packet_callback(c->pstream, pstream_packet_callback, c);
5049 pa_pstream_set_receive_memblock_callback(c->pstream, pstream_memblock_callback, c);
5050 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
5051 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
5052 pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
5053 pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
5054
5055 c->pdispatch = pa_pdispatch_new(p->core->mainloop, true, command_table, PA_COMMAND_MAX);
5056
5057 c->record_streams = pa_idxset_new(NULL, NULL);
5058 c->output_streams = pa_idxset_new(NULL, NULL);
5059
5060 c->rrobin_index = PA_IDXSET_INVALID;
5061 c->subscription = NULL;
5062
5063 pa_idxset_put(p->connections, c, NULL);
5064
5065 #ifdef HAVE_CREDS
5066 if (pa_iochannel_creds_supported(io))
5067 pa_iochannel_creds_enable(io);
5068 #endif
5069
5070 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
5071 }
5072
5073 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
5074 pa_native_connection *c;
5075 void *state = NULL;
5076
5077 pa_assert(p);
5078 pa_assert(m);
5079
5080 while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
5081 if (c->options->module == m)
5082 native_connection_unlink(c);
5083 }
5084
5085 static pa_native_protocol* native_protocol_new(pa_core *c) {
5086 pa_native_protocol *p;
5087 pa_native_hook_t h;
5088
5089 pa_assert(c);
5090
5091 p = pa_xnew(pa_native_protocol, 1);
5092 PA_REFCNT_INIT(p);
5093 p->core = c;
5094 p->connections = pa_idxset_new(NULL, NULL);
5095
5096 p->servers = NULL;
5097
5098 p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
5099
5100 for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
5101 pa_hook_init(&p->hooks[h], p);
5102
5103 pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
5104
5105 return p;
5106 }
5107
5108 pa_native_protocol* pa_native_protocol_get(pa_core *c) {
5109 pa_native_protocol *p;
5110
5111 if ((p = pa_shared_get(c, "native-protocol")))
5112 return pa_native_protocol_ref(p);
5113
5114 return native_protocol_new(c);
5115 }
5116
5117 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
5118 pa_assert(p);
5119 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5120
5121 PA_REFCNT_INC(p);
5122
5123 return p;
5124 }
5125
5126 void pa_native_protocol_unref(pa_native_protocol *p) {
5127 pa_native_connection *c;
5128 pa_native_hook_t h;
5129
5130 pa_assert(p);
5131 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5132
5133 if (PA_REFCNT_DEC(p) > 0)
5134 return;
5135
5136 while ((c = pa_idxset_first(p->connections, NULL)))
5137 native_connection_unlink(c);
5138
5139 pa_idxset_free(p->connections, NULL);
5140
5141 pa_strlist_free(p->servers);
5142
5143 for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
5144 pa_hook_done(&p->hooks[h]);
5145
5146 pa_hashmap_free(p->extensions);
5147
5148 pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
5149
5150 pa_xfree(p);
5151 }
5152
5153 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name) {
5154 pa_assert(p);
5155 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5156 pa_assert(name);
5157
5158 p->servers = pa_strlist_prepend(p->servers, name);
5159
5160 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
5161 }
5162
5163 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
5164 pa_assert(p);
5165 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5166 pa_assert(name);
5167
5168 p->servers = pa_strlist_remove(p->servers, name);
5169
5170 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
5171 }
5172
5173 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
5174 pa_assert(p);
5175 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5176
5177 return p->hooks;
5178 }
5179
5180 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
5181 pa_assert(p);
5182 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5183
5184 return p->servers;
5185 }
5186
5187 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb) {
5188 pa_assert(p);
5189 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5190 pa_assert(m);
5191 pa_assert(cb);
5192 pa_assert(!pa_hashmap_get(p->extensions, m));
5193
5194 pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) (unsigned long) cb) == 0);
5195 return 0;
5196 }
5197
5198 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
5199 pa_assert(p);
5200 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5201 pa_assert(m);
5202
5203 pa_assert_se(pa_hashmap_remove(p->extensions, m));
5204 }
5205
5206 pa_native_options* pa_native_options_new(void) {
5207 pa_native_options *o;
5208
5209 o = pa_xnew0(pa_native_options, 1);
5210 PA_REFCNT_INIT(o);
5211
5212 return o;
5213 }
5214
5215 pa_native_options* pa_native_options_ref(pa_native_options *o) {
5216 pa_assert(o);
5217 pa_assert(PA_REFCNT_VALUE(o) >= 1);
5218
5219 PA_REFCNT_INC(o);
5220
5221 return o;
5222 }
5223
5224 void pa_native_options_unref(pa_native_options *o) {
5225 pa_assert(o);
5226 pa_assert(PA_REFCNT_VALUE(o) >= 1);
5227
5228 if (PA_REFCNT_DEC(o) > 0)
5229 return;
5230
5231 pa_xfree(o->auth_group);
5232
5233 if (o->auth_ip_acl)
5234 pa_ip_acl_free(o->auth_ip_acl);
5235
5236 if (o->auth_cookie)
5237 pa_auth_cookie_unref(o->auth_cookie);
5238
5239 pa_xfree(o);
5240 }
5241
5242 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
5243 bool enabled;
5244 const char *acl;
5245
5246 pa_assert(o);
5247 pa_assert(PA_REFCNT_VALUE(o) >= 1);
5248 pa_assert(ma);
5249
5250 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
5251 pa_log("auth-anonymous= expects a boolean argument.");
5252 return -1;
5253 }
5254
5255 enabled = true;
5256 if (pa_modargs_get_value_boolean(ma, "auth-group-enable", &enabled) < 0) {
5257 pa_log("auth-group-enable= expects a boolean argument.");
5258 return -1;
5259 }
5260
5261 pa_xfree(o->auth_group);
5262 o->auth_group = enabled ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
5263
5264 #ifndef HAVE_CREDS
5265 if (o->auth_group)
5266 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
5267 #endif
5268
5269 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
5270 pa_ip_acl *ipa;
5271
5272 if (!(ipa = pa_ip_acl_new(acl))) {
5273 pa_log("Failed to parse IP ACL '%s'", acl);
5274 return -1;
5275 }
5276
5277 if (o->auth_ip_acl)
5278 pa_ip_acl_free(o->auth_ip_acl);
5279
5280 o->auth_ip_acl = ipa;
5281 }
5282
5283 enabled = true;
5284 if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
5285 pa_log("auth-cookie-enabled= expects a boolean argument.");
5286 return -1;
5287 }
5288
5289 if (o->auth_cookie)
5290 pa_auth_cookie_unref(o->auth_cookie);
5291
5292 if (enabled) {
5293 const char *cn;
5294
5295 /* The new name for this is 'auth-cookie', for compat reasons
5296 * we check the old name too */
5297 cn = pa_modargs_get_value(ma, "auth-cookie", NULL);
5298 if (!cn)
5299 cn = pa_modargs_get_value(ma, "cookie", NULL);
5300
5301 if (cn)
5302 o->auth_cookie = pa_auth_cookie_get(c, cn, true, PA_NATIVE_COOKIE_LENGTH);
5303 else {
5304 o->auth_cookie = pa_auth_cookie_get(c, PA_NATIVE_COOKIE_FILE, false, PA_NATIVE_COOKIE_LENGTH);
5305 if (!o->auth_cookie) {
5306 o->auth_cookie = pa_auth_cookie_get(c, PA_NATIVE_COOKIE_FILE_FALLBACK, false, PA_NATIVE_COOKIE_LENGTH);
5307
5308 if (!o->auth_cookie)
5309 o->auth_cookie = pa_auth_cookie_get(c, PA_NATIVE_COOKIE_FILE, true, PA_NATIVE_COOKIE_LENGTH);
5310 }
5311 }
5312
5313 if (!o->auth_cookie)
5314 return -1;
5315
5316 } else
5317 o->auth_cookie = NULL;
5318
5319 return 0;
5320 }
5321
5322 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
5323 pa_native_connection_assert_ref(c);
5324
5325 return c->pstream;
5326 }
5327
5328 pa_client* pa_native_connection_get_client(pa_native_connection *c) {
5329 pa_native_connection_assert_ref(c);
5330
5331 return c->client;
5332 }