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