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