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