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