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