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