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