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