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