]> code.delx.au - pulseaudio/blob - src/pulsecore/protocol-native.c
6b98175444cff8169c448c1cbc17d0ce5fc094f4
[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;
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 = TRUE,
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
2338 if (pa_tagstruct_getu8(t, &n_formats) < 0) {
2339 protocol_error(c);
2340 goto finish;
2341 }
2342
2343 if (n_formats)
2344 formats = pa_idxset_new(NULL, NULL);
2345
2346 for (i = 0; i < n_formats; i++) {
2347 format = pa_format_info_new();
2348 if (pa_tagstruct_get_format_info(t, format) < 0) {
2349 protocol_error(c);
2350 goto finish;
2351 }
2352 pa_idxset_put(formats, format, NULL);
2353 }
2354
2355 if (pa_tagstruct_get_cvolume(t, &volume) < 0 ||
2356 pa_tagstruct_get_boolean(t, &muted) < 0 ||
2357 pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
2358 pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
2359 pa_tagstruct_get_boolean(t, &relative_volume) < 0 ||
2360 pa_tagstruct_get_boolean(t, &passthrough) < 0) {
2361
2362 protocol_error(c);
2363 goto finish;
2364 }
2365
2366 CHECK_VALIDITY_GOTO(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID, finish);
2367 }
2368
2369 if (n_formats == 0) {
2370 CHECK_VALIDITY_GOTO(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID, finish);
2371 CHECK_VALIDITY_GOTO(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID, finish);
2372 CHECK_VALIDITY_GOTO(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID, finish);
2373 } else {
2374 PA_IDXSET_FOREACH(format, formats, i) {
2375 CHECK_VALIDITY_GOTO(c->pstream, pa_format_info_valid(format), tag, PA_ERR_INVALID, finish);
2376 }
2377 }
2378
2379
2380 if (!pa_tagstruct_eof(t)) {
2381 protocol_error(c);
2382 goto finish;
2383 }
2384
2385 if (source_index != PA_INVALID_INDEX) {
2386
2387 if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
2388 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2389 goto finish;
2390 }
2391
2392 } else if (source_name) {
2393
2394 if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE))) {
2395 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2396 goto finish;
2397 }
2398 }
2399
2400 if (direct_on_input_idx != PA_INVALID_INDEX) {
2401
2402 if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
2403 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2404 goto finish;
2405 }
2406 }
2407
2408 flags =
2409 (corked ? PA_SOURCE_OUTPUT_START_CORKED : 0) |
2410 (no_remap ? PA_SOURCE_OUTPUT_NO_REMAP : 0) |
2411 (no_remix ? PA_SOURCE_OUTPUT_NO_REMIX : 0) |
2412 (fix_format ? PA_SOURCE_OUTPUT_FIX_FORMAT : 0) |
2413 (fix_rate ? PA_SOURCE_OUTPUT_FIX_RATE : 0) |
2414 (fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
2415 (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
2416 (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
2417 (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2418 (fail_on_suspend ? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND : 0) |
2419 (passthrough ? PA_SOURCE_OUTPUT_PASSTHROUGH : 0);
2420
2421 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);
2422
2423 CHECK_VALIDITY_GOTO(c->pstream, s, tag, ret, finish);
2424
2425 reply = reply_new(tag);
2426 pa_tagstruct_putu32(reply, s->index);
2427 pa_assert(s->source_output);
2428 pa_tagstruct_putu32(reply, s->source_output->index);
2429
2430 if (c->version >= 9) {
2431 /* Since 0.9 we support sending the buffer metrics back to the client */
2432
2433 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2434 pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.fragsize);
2435 }
2436
2437 if (c->version >= 12) {
2438 /* Since 0.9.8 we support sending the chosen sample
2439 * spec/channel map/device/suspend status back to the
2440 * client */
2441
2442 pa_tagstruct_put_sample_spec(reply, &ss);
2443 pa_tagstruct_put_channel_map(reply, &map);
2444
2445 pa_tagstruct_putu32(reply, s->source_output->source->index);
2446 pa_tagstruct_puts(reply, s->source_output->source->name);
2447
2448 pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED);
2449 }
2450
2451 if (c->version >= 13)
2452 pa_tagstruct_put_usec(reply, s->configured_source_latency);
2453
2454 if (c->version >= 22) {
2455 /* Send back the format we negotiated */
2456 if (s->source_output->format)
2457 pa_tagstruct_put_format_info(reply, s->source_output->format);
2458 else {
2459 pa_format_info *f = pa_format_info_new();
2460 pa_tagstruct_put_format_info(reply, f);
2461 pa_format_info_free(f);
2462 }
2463 }
2464
2465 pa_pstream_send_tagstruct(c->pstream, reply);
2466
2467 finish:
2468 if (p)
2469 pa_proplist_free(p);
2470 if (formats)
2471 pa_idxset_free(formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
2472 }
2473
2474 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2475 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2476 int ret;
2477
2478 pa_native_connection_assert_ref(c);
2479 pa_assert(t);
2480
2481 if (!pa_tagstruct_eof(t)) {
2482 protocol_error(c);
2483 return;
2484 }
2485
2486 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2487 ret = pa_core_exit(c->protocol->core, FALSE, 0);
2488 CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
2489
2490 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY)));
2491
2492 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
2493 }
2494
2495 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2496 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2497 const void*cookie;
2498 pa_tagstruct *reply;
2499 pa_bool_t shm_on_remote = FALSE, do_shm;
2500
2501 pa_native_connection_assert_ref(c);
2502 pa_assert(t);
2503
2504 if (pa_tagstruct_getu32(t, &c->version) < 0 ||
2505 pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
2506 !pa_tagstruct_eof(t)) {
2507 protocol_error(c);
2508 return;
2509 }
2510
2511 /* Minimum supported version */
2512 if (c->version < 8) {
2513 pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
2514 return;
2515 }
2516
2517 /* Starting with protocol version 13 the MSB of the version tag
2518 reflects if shm is available for this pa_native_connection or
2519 not. */
2520 if (c->version >= 13) {
2521 shm_on_remote = !!(c->version & 0x80000000U);
2522 c->version &= 0x7FFFFFFFU;
2523 }
2524
2525 pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
2526
2527 pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
2528
2529 if (!c->authorized) {
2530 pa_bool_t success = FALSE;
2531
2532 #ifdef HAVE_CREDS
2533 const pa_creds *creds;
2534
2535 if ((creds = pa_pdispatch_creds(pd))) {
2536 if (creds->uid == getuid())
2537 success = TRUE;
2538 else if (c->options->auth_group) {
2539 int r;
2540 gid_t gid;
2541
2542 if ((gid = pa_get_gid_of_group(c->options->auth_group)) == (gid_t) -1)
2543 pa_log_warn("Failed to get GID of group '%s'", c->options->auth_group);
2544 else if (gid == creds->gid)
2545 success = TRUE;
2546
2547 if (!success) {
2548 if ((r = pa_uid_in_group(creds->uid, c->options->auth_group)) < 0)
2549 pa_log_warn("Failed to check group membership.");
2550 else if (r > 0)
2551 success = TRUE;
2552 }
2553 }
2554
2555 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2556 (unsigned long) creds->uid,
2557 (unsigned long) creds->gid,
2558 (int) success);
2559 }
2560 #endif
2561
2562 if (!success && c->options->auth_cookie) {
2563 const uint8_t *ac;
2564
2565 if ((ac = pa_auth_cookie_read(c->options->auth_cookie, PA_NATIVE_COOKIE_LENGTH)))
2566 if (memcmp(ac, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
2567 success = TRUE;
2568 }
2569
2570 if (!success) {
2571 pa_log_warn("Denied access to client with invalid authorization data.");
2572 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2573 return;
2574 }
2575
2576 c->authorized = TRUE;
2577 if (c->auth_timeout_event) {
2578 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
2579 c->auth_timeout_event = NULL;
2580 }
2581 }
2582
2583 /* Enable shared memory support if possible */
2584 do_shm =
2585 pa_mempool_is_shared(c->protocol->core->mempool) &&
2586 c->is_local;
2587
2588 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm));
2589
2590 if (do_shm)
2591 if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
2592 do_shm = FALSE;
2593
2594 #ifdef HAVE_CREDS
2595 if (do_shm) {
2596 /* Only enable SHM if both sides are owned by the same
2597 * user. This is a security measure because otherwise data
2598 * private to the user might leak. */
2599
2600 const pa_creds *creds;
2601 if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
2602 do_shm = FALSE;
2603 }
2604 #endif
2605
2606 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
2607 pa_pstream_enable_shm(c->pstream, do_shm);
2608
2609 reply = reply_new(tag);
2610 pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0));
2611
2612 #ifdef HAVE_CREDS
2613 {
2614 /* SHM support is only enabled after both sides made sure they are the same user. */
2615
2616 pa_creds ucred;
2617
2618 ucred.uid = getuid();
2619 ucred.gid = getgid();
2620
2621 pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
2622 }
2623 #else
2624 pa_pstream_send_tagstruct(c->pstream, reply);
2625 #endif
2626 }
2627
2628 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2629 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2630 const char *name = NULL;
2631 pa_proplist *p;
2632 pa_tagstruct *reply;
2633
2634 pa_native_connection_assert_ref(c);
2635 pa_assert(t);
2636
2637 p = pa_proplist_new();
2638
2639 if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
2640 (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2641 !pa_tagstruct_eof(t)) {
2642
2643 protocol_error(c);
2644 pa_proplist_free(p);
2645 return;
2646 }
2647
2648 if (name)
2649 if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
2650 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2651 pa_proplist_free(p);
2652 return;
2653 }
2654
2655 pa_client_update_proplist(c->client, PA_UPDATE_REPLACE, p);
2656 pa_proplist_free(p);
2657
2658 reply = reply_new(tag);
2659
2660 if (c->version >= 13)
2661 pa_tagstruct_putu32(reply, c->client->index);
2662
2663 pa_pstream_send_tagstruct(c->pstream, reply);
2664 }
2665
2666 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2667 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2668 const char *name;
2669 uint32_t idx = PA_IDXSET_INVALID;
2670
2671 pa_native_connection_assert_ref(c);
2672 pa_assert(t);
2673
2674 if (pa_tagstruct_gets(t, &name) < 0 ||
2675 !pa_tagstruct_eof(t)) {
2676 protocol_error(c);
2677 return;
2678 }
2679
2680 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2681 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);
2682
2683 if (command == PA_COMMAND_LOOKUP_SINK) {
2684 pa_sink *sink;
2685 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK)))
2686 idx = sink->index;
2687 } else {
2688 pa_source *source;
2689 pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
2690 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE)))
2691 idx = source->index;
2692 }
2693
2694 if (idx == PA_IDXSET_INVALID)
2695 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2696 else {
2697 pa_tagstruct *reply;
2698 reply = reply_new(tag);
2699 pa_tagstruct_putu32(reply, idx);
2700 pa_pstream_send_tagstruct(c->pstream, reply);
2701 }
2702 }
2703
2704 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2705 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2706 uint32_t idx;
2707 playback_stream *s;
2708
2709 pa_native_connection_assert_ref(c);
2710 pa_assert(t);
2711
2712 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2713 !pa_tagstruct_eof(t)) {
2714 protocol_error(c);
2715 return;
2716 }
2717
2718 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2719 s = pa_idxset_get_by_index(c->output_streams, idx);
2720 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2721 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2722
2723 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);
2724 }
2725
2726 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2727 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2728 pa_tagstruct *reply;
2729 const pa_mempool_stat *stat;
2730
2731 pa_native_connection_assert_ref(c);
2732 pa_assert(t);
2733
2734 if (!pa_tagstruct_eof(t)) {
2735 protocol_error(c);
2736 return;
2737 }
2738
2739 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2740
2741 stat = pa_mempool_get_stat(c->protocol->core->mempool);
2742
2743 reply = reply_new(tag);
2744 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
2745 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
2746 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
2747 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
2748 pa_tagstruct_putu32(reply, (uint32_t) pa_scache_total_size(c->protocol->core));
2749 pa_pstream_send_tagstruct(c->pstream, reply);
2750 }
2751
2752 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2753 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2754 pa_tagstruct *reply;
2755 playback_stream *s;
2756 struct timeval tv, now;
2757 uint32_t idx;
2758
2759 pa_native_connection_assert_ref(c);
2760 pa_assert(t);
2761
2762 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2763 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2764 !pa_tagstruct_eof(t)) {
2765 protocol_error(c);
2766 return;
2767 }
2768
2769 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2770 s = pa_idxset_get_by_index(c->output_streams, idx);
2771 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2772 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2773
2774 /* Get an atomic snapshot of all timing parameters */
2775 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);
2776
2777 reply = reply_new(tag);
2778 pa_tagstruct_put_usec(reply,
2779 s->current_sink_latency +
2780 pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sink->sample_spec));
2781 pa_tagstruct_put_usec(reply, 0);
2782 pa_tagstruct_put_boolean(reply,
2783 s->playing_for > 0 &&
2784 pa_sink_get_state(s->sink_input->sink) == PA_SINK_RUNNING &&
2785 pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
2786 pa_tagstruct_put_timeval(reply, &tv);
2787 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2788 pa_tagstruct_puts64(reply, s->write_index);
2789 pa_tagstruct_puts64(reply, s->read_index);
2790
2791 if (c->version >= 13) {
2792 pa_tagstruct_putu64(reply, s->underrun_for);
2793 pa_tagstruct_putu64(reply, s->playing_for);
2794 }
2795
2796 pa_pstream_send_tagstruct(c->pstream, reply);
2797 }
2798
2799 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2800 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2801 pa_tagstruct *reply;
2802 record_stream *s;
2803 struct timeval tv, now;
2804 uint32_t idx;
2805
2806 pa_native_connection_assert_ref(c);
2807 pa_assert(t);
2808
2809 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2810 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2811 !pa_tagstruct_eof(t)) {
2812 protocol_error(c);
2813 return;
2814 }
2815
2816 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2817 s = pa_idxset_get_by_index(c->record_streams, idx);
2818 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2819
2820 /* Get an atomic snapshot of all timing parameters */
2821 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);
2822
2823 reply = reply_new(tag);
2824 pa_tagstruct_put_usec(reply, s->current_monitor_latency);
2825 pa_tagstruct_put_usec(reply,
2826 s->current_source_latency +
2827 pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->source->sample_spec));
2828 pa_tagstruct_put_boolean(reply,
2829 pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING &&
2830 pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING);
2831 pa_tagstruct_put_timeval(reply, &tv);
2832 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2833 pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
2834 pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
2835 pa_pstream_send_tagstruct(c->pstream, reply);
2836 }
2837
2838 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2839 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2840 upload_stream *s;
2841 uint32_t length;
2842 const char *name = NULL;
2843 pa_sample_spec ss;
2844 pa_channel_map map;
2845 pa_tagstruct *reply;
2846 pa_proplist *p;
2847
2848 pa_native_connection_assert_ref(c);
2849 pa_assert(t);
2850
2851 if (pa_tagstruct_gets(t, &name) < 0 ||
2852 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2853 pa_tagstruct_get_channel_map(t, &map) < 0 ||
2854 pa_tagstruct_getu32(t, &length) < 0) {
2855 protocol_error(c);
2856 return;
2857 }
2858
2859 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2860 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2861 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2862 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2863 CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
2864 CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
2865
2866 p = pa_proplist_new();
2867
2868 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2869 !pa_tagstruct_eof(t)) {
2870
2871 protocol_error(c);
2872 pa_proplist_free(p);
2873 return;
2874 }
2875
2876 if (c->version < 13)
2877 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2878 else if (!name)
2879 if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID)))
2880 name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME);
2881
2882 if (!name || !pa_namereg_is_valid_name(name)) {
2883 pa_proplist_free(p);
2884 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
2885 }
2886
2887 s = upload_stream_new(c, &ss, &map, name, length, p);
2888 pa_proplist_free(p);
2889
2890 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
2891
2892 reply = reply_new(tag);
2893 pa_tagstruct_putu32(reply, s->index);
2894 pa_tagstruct_putu32(reply, length);
2895 pa_pstream_send_tagstruct(c->pstream, reply);
2896 }
2897
2898 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2899 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2900 uint32_t channel;
2901 upload_stream *s;
2902 uint32_t idx;
2903
2904 pa_native_connection_assert_ref(c);
2905 pa_assert(t);
2906
2907 if (pa_tagstruct_getu32(t, &channel) < 0 ||
2908 !pa_tagstruct_eof(t)) {
2909 protocol_error(c);
2910 return;
2911 }
2912
2913 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2914
2915 s = pa_idxset_get_by_index(c->output_streams, channel);
2916 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2917 CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2918
2919 if (!s->memchunk.memblock)
2920 pa_pstream_send_error(c->pstream, tag, PA_ERR_TOOLARGE);
2921 else if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
2922 pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
2923 else
2924 pa_pstream_send_simple_ack(c->pstream, tag);
2925
2926 upload_stream_unlink(s);
2927 }
2928
2929 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2930 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2931 uint32_t sink_index;
2932 pa_volume_t volume;
2933 pa_sink *sink;
2934 const char *name, *sink_name;
2935 uint32_t idx;
2936 pa_proplist *p;
2937 pa_tagstruct *reply;
2938
2939 pa_native_connection_assert_ref(c);
2940 pa_assert(t);
2941
2942 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2943
2944 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
2945 pa_tagstruct_gets(t, &sink_name) < 0 ||
2946 pa_tagstruct_getu32(t, &volume) < 0 ||
2947 pa_tagstruct_gets(t, &name) < 0) {
2948 protocol_error(c);
2949 return;
2950 }
2951
2952 CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
2953 CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
2954 CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2955 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2956
2957 if (sink_index != PA_INVALID_INDEX)
2958 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
2959 else
2960 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK);
2961
2962 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
2963
2964 p = pa_proplist_new();
2965
2966 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2967 !pa_tagstruct_eof(t)) {
2968 protocol_error(c);
2969 pa_proplist_free(p);
2970 return;
2971 }
2972
2973 pa_proplist_update(p, PA_UPDATE_MERGE, c->client->proplist);
2974
2975 if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
2976 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2977 pa_proplist_free(p);
2978 return;
2979 }
2980
2981 pa_proplist_free(p);
2982
2983 reply = reply_new(tag);
2984
2985 if (c->version >= 13)
2986 pa_tagstruct_putu32(reply, idx);
2987
2988 pa_pstream_send_tagstruct(c->pstream, reply);
2989 }
2990
2991 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2992 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2993 const char *name;
2994
2995 pa_native_connection_assert_ref(c);
2996 pa_assert(t);
2997
2998 if (pa_tagstruct_gets(t, &name) < 0 ||
2999 !pa_tagstruct_eof(t)) {
3000 protocol_error(c);
3001 return;
3002 }
3003
3004 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3005 CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3006
3007 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
3008 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3009 return;
3010 }
3011
3012 pa_pstream_send_simple_ack(c->pstream, tag);
3013 }
3014
3015 static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
3016 pa_assert(c);
3017 pa_assert(fixed);
3018 pa_assert(original);
3019
3020 *fixed = *original;
3021
3022 if (c->version < 12) {
3023 /* Before protocol version 12 we didn't support S32 samples,
3024 * so we need to lie about this to the client */
3025
3026 if (fixed->format == PA_SAMPLE_S32LE)
3027 fixed->format = PA_SAMPLE_FLOAT32LE;
3028 if (fixed->format == PA_SAMPLE_S32BE)
3029 fixed->format = PA_SAMPLE_FLOAT32BE;
3030 }
3031
3032 if (c->version < 15) {
3033 if (fixed->format == PA_SAMPLE_S24LE || fixed->format == PA_SAMPLE_S24_32LE)
3034 fixed->format = PA_SAMPLE_FLOAT32LE;
3035 if (fixed->format == PA_SAMPLE_S24BE || fixed->format == PA_SAMPLE_S24_32BE)
3036 fixed->format = PA_SAMPLE_FLOAT32BE;
3037 }
3038 }
3039
3040 static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) {
3041 pa_sample_spec fixed_ss;
3042
3043 pa_assert(t);
3044 pa_sink_assert_ref(sink);
3045
3046 fixup_sample_spec(c, &fixed_ss, &sink->sample_spec);
3047
3048 pa_tagstruct_put(
3049 t,
3050 PA_TAG_U32, sink->index,
3051 PA_TAG_STRING, sink->name,
3052 PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
3053 PA_TAG_SAMPLE_SPEC, &fixed_ss,
3054 PA_TAG_CHANNEL_MAP, &sink->channel_map,
3055 PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
3056 PA_TAG_CVOLUME, pa_sink_get_volume(sink, FALSE),
3057 PA_TAG_BOOLEAN, pa_sink_get_mute(sink, FALSE),
3058 PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
3059 PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
3060 PA_TAG_USEC, pa_sink_get_latency(sink),
3061 PA_TAG_STRING, sink->driver,
3062 PA_TAG_U32, sink->flags & ~PA_SINK_SHARE_VOLUME_WITH_MASTER,
3063 PA_TAG_INVALID);
3064
3065 if (c->version >= 13) {
3066 pa_tagstruct_put_proplist(t, sink->proplist);
3067 pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
3068 }
3069
3070 if (c->version >= 15) {
3071 pa_tagstruct_put_volume(t, sink->base_volume);
3072 if (PA_UNLIKELY(pa_sink_get_state(sink) == PA_SINK_INVALID_STATE))
3073 pa_log_error("Internal sink state is invalid.");
3074 pa_tagstruct_putu32(t, pa_sink_get_state(sink));
3075 pa_tagstruct_putu32(t, sink->n_volume_steps);
3076 pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX);
3077 }
3078
3079 if (c->version >= 16) {
3080 pa_tagstruct_putu32(t, sink->ports ? pa_hashmap_size(sink->ports) : 0);
3081
3082 if (sink->ports) {
3083 void *state;
3084 pa_device_port *p;
3085
3086 PA_HASHMAP_FOREACH(p, sink->ports, state) {
3087 pa_tagstruct_puts(t, p->name);
3088 pa_tagstruct_puts(t, p->description);
3089 pa_tagstruct_putu32(t, p->priority);
3090 }
3091 }
3092
3093 pa_tagstruct_puts(t, sink->active_port ? sink->active_port->name : NULL);
3094 }
3095
3096 if (c->version >= 21) {
3097 uint32_t i;
3098 pa_format_info *f;
3099 pa_idxset *formats = pa_sink_get_formats(sink);
3100
3101 pa_tagstruct_putu8(t, (uint8_t) pa_idxset_size(formats));
3102 PA_IDXSET_FOREACH(f, formats, i) {
3103 pa_tagstruct_put_format_info(t, f);
3104 }
3105
3106 pa_idxset_free(formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
3107 }
3108 }
3109
3110 static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
3111 pa_sample_spec fixed_ss;
3112
3113 pa_assert(t);
3114 pa_source_assert_ref(source);
3115
3116 fixup_sample_spec(c, &fixed_ss, &source->sample_spec);
3117
3118 pa_tagstruct_put(
3119 t,
3120 PA_TAG_U32, source->index,
3121 PA_TAG_STRING, source->name,
3122 PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
3123 PA_TAG_SAMPLE_SPEC, &fixed_ss,
3124 PA_TAG_CHANNEL_MAP, &source->channel_map,
3125 PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
3126 PA_TAG_CVOLUME, pa_source_get_volume(source, FALSE),
3127 PA_TAG_BOOLEAN, pa_source_get_mute(source, FALSE),
3128 PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
3129 PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
3130 PA_TAG_USEC, pa_source_get_latency(source),
3131 PA_TAG_STRING, source->driver,
3132 PA_TAG_U32, source->flags,
3133 PA_TAG_INVALID);
3134
3135 if (c->version >= 13) {
3136 pa_tagstruct_put_proplist(t, source->proplist);
3137 pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
3138 }
3139
3140 if (c->version >= 15) {
3141 pa_tagstruct_put_volume(t, source->base_volume);
3142 if (PA_UNLIKELY(pa_source_get_state(source) == PA_SOURCE_INVALID_STATE))
3143 pa_log_error("Internal source state is invalid.");
3144 pa_tagstruct_putu32(t, pa_source_get_state(source));
3145 pa_tagstruct_putu32(t, source->n_volume_steps);
3146 pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX);
3147 }
3148
3149 if (c->version >= 16) {
3150
3151 pa_tagstruct_putu32(t, source->ports ? pa_hashmap_size(source->ports) : 0);
3152
3153 if (source->ports) {
3154 void *state;
3155 pa_device_port *p;
3156
3157 PA_HASHMAP_FOREACH(p, source->ports, state) {
3158 pa_tagstruct_puts(t, p->name);
3159 pa_tagstruct_puts(t, p->description);
3160 pa_tagstruct_putu32(t, p->priority);
3161 }
3162 }
3163
3164 pa_tagstruct_puts(t, source->active_port ? source->active_port->name : NULL);
3165 }
3166
3167 if (c->version >= 22) {
3168 uint32_t i;
3169 pa_format_info *f;
3170 pa_idxset *formats = pa_source_get_formats(source);
3171
3172 pa_tagstruct_putu8(t, (uint8_t) pa_idxset_size(formats));
3173 PA_IDXSET_FOREACH(f, formats, i) {
3174 pa_tagstruct_put_format_info(t, f);
3175 }
3176
3177 pa_idxset_free(formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
3178 }
3179 }
3180
3181 static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
3182 pa_assert(t);
3183 pa_assert(client);
3184
3185 pa_tagstruct_putu32(t, client->index);
3186 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
3187 pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
3188 pa_tagstruct_puts(t, client->driver);
3189
3190 if (c->version >= 13)
3191 pa_tagstruct_put_proplist(t, client->proplist);
3192 }
3193
3194 static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
3195 void *state = NULL;
3196 pa_card_profile *p;
3197
3198 pa_assert(t);
3199 pa_assert(card);
3200
3201 pa_tagstruct_putu32(t, card->index);
3202 pa_tagstruct_puts(t, card->name);
3203 pa_tagstruct_putu32(t, card->module ? card->module->index : PA_INVALID_INDEX);
3204 pa_tagstruct_puts(t, card->driver);
3205
3206 pa_tagstruct_putu32(t, card->profiles ? pa_hashmap_size(card->profiles) : 0);
3207
3208 if (card->profiles) {
3209 while ((p = pa_hashmap_iterate(card->profiles, &state, NULL))) {
3210 pa_tagstruct_puts(t, p->name);
3211 pa_tagstruct_puts(t, p->description);
3212 pa_tagstruct_putu32(t, p->n_sinks);
3213 pa_tagstruct_putu32(t, p->n_sources);
3214 pa_tagstruct_putu32(t, p->priority);
3215 }
3216 }
3217
3218 pa_tagstruct_puts(t, card->active_profile ? card->active_profile->name : NULL);
3219 pa_tagstruct_put_proplist(t, card->proplist);
3220 }
3221
3222 static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module) {
3223 pa_assert(t);
3224 pa_assert(module);
3225
3226 pa_tagstruct_putu32(t, module->index);
3227 pa_tagstruct_puts(t, module->name);
3228 pa_tagstruct_puts(t, module->argument);
3229 pa_tagstruct_putu32(t, (uint32_t) pa_module_get_n_used(module));
3230
3231 if (c->version < 15)
3232 pa_tagstruct_put_boolean(t, FALSE); /* autoload is obsolete */
3233
3234 if (c->version >= 15)
3235 pa_tagstruct_put_proplist(t, module->proplist);
3236 }
3237
3238 static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) {
3239 pa_sample_spec fixed_ss;
3240 pa_usec_t sink_latency;
3241 pa_cvolume v;
3242 pa_bool_t has_volume = FALSE;
3243
3244 pa_assert(t);
3245 pa_sink_input_assert_ref(s);
3246
3247 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3248
3249 has_volume = pa_sink_input_is_volume_readable(s);
3250 if (has_volume)
3251 pa_sink_input_get_volume(s, &v, TRUE);
3252 else
3253 pa_cvolume_reset(&v, fixed_ss.channels);
3254
3255 pa_tagstruct_putu32(t, s->index);
3256 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3257 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3258 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3259 pa_tagstruct_putu32(t, s->sink->index);
3260 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3261 pa_tagstruct_put_channel_map(t, &s->channel_map);
3262 pa_tagstruct_put_cvolume(t, &v);
3263 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
3264 pa_tagstruct_put_usec(t, sink_latency);
3265 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
3266 pa_tagstruct_puts(t, s->driver);
3267 if (c->version >= 11)
3268 pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
3269 if (c->version >= 13)
3270 pa_tagstruct_put_proplist(t, s->proplist);
3271 if (c->version >= 19)
3272 pa_tagstruct_put_boolean(t, (pa_sink_input_get_state(s) == PA_SINK_INPUT_CORKED));
3273 if (c->version >= 20) {
3274 pa_tagstruct_put_boolean(t, has_volume);
3275 pa_tagstruct_put_boolean(t, s->volume_writable);
3276 }
3277 if (c->version >= 21)
3278 pa_tagstruct_put_format_info(t, s->format);
3279 }
3280
3281 static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
3282 pa_sample_spec fixed_ss;
3283 pa_usec_t source_latency;
3284 pa_cvolume v;
3285 pa_bool_t has_volume = FALSE;
3286
3287 pa_assert(t);
3288 pa_source_output_assert_ref(s);
3289
3290 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3291
3292 has_volume = pa_source_output_is_volume_readable(s);
3293 if (has_volume)
3294 pa_source_output_get_volume(s, &v, TRUE);
3295 else
3296 pa_cvolume_reset(&v, fixed_ss.channels);
3297
3298 pa_tagstruct_putu32(t, s->index);
3299 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3300 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3301 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3302 pa_tagstruct_putu32(t, s->source->index);
3303 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3304 pa_tagstruct_put_channel_map(t, &s->channel_map);
3305 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s, &source_latency));
3306 pa_tagstruct_put_usec(t, source_latency);
3307 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
3308 pa_tagstruct_puts(t, s->driver);
3309 if (c->version >= 13)
3310 pa_tagstruct_put_proplist(t, s->proplist);
3311 if (c->version >= 19)
3312 pa_tagstruct_put_boolean(t, (pa_source_output_get_state(s) == PA_SOURCE_OUTPUT_CORKED));
3313 if (c->version >= 22) {
3314 pa_tagstruct_put_cvolume(t, &v);
3315 pa_tagstruct_put_boolean(t, pa_source_output_get_mute(s));
3316 pa_tagstruct_put_boolean(t, has_volume);
3317 pa_tagstruct_put_boolean(t, s->volume_writable);
3318 pa_tagstruct_put_format_info(t, s->format);
3319 }
3320 }
3321
3322 static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {
3323 pa_sample_spec fixed_ss;
3324 pa_cvolume v;
3325
3326 pa_assert(t);
3327 pa_assert(e);
3328
3329 if (e->memchunk.memblock)
3330 fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
3331 else
3332 memset(&fixed_ss, 0, sizeof(fixed_ss));
3333
3334 pa_tagstruct_putu32(t, e->index);
3335 pa_tagstruct_puts(t, e->name);
3336
3337 if (e->volume_is_set)
3338 v = e->volume;
3339 else
3340 pa_cvolume_init(&v);
3341
3342 pa_tagstruct_put_cvolume(t, &v);
3343 pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0);
3344 pa_tagstruct_put_sample_spec(t, &fixed_ss);
3345 pa_tagstruct_put_channel_map(t, &e->channel_map);
3346 pa_tagstruct_putu32(t, (uint32_t) e->memchunk.length);
3347 pa_tagstruct_put_boolean(t, e->lazy);
3348 pa_tagstruct_puts(t, e->filename);
3349
3350 if (c->version >= 13)
3351 pa_tagstruct_put_proplist(t, e->proplist);
3352 }
3353
3354 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3355 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3356 uint32_t idx;
3357 pa_sink *sink = NULL;
3358 pa_source *source = NULL;
3359 pa_client *client = NULL;
3360 pa_card *card = NULL;
3361 pa_module *module = NULL;
3362 pa_sink_input *si = NULL;
3363 pa_source_output *so = NULL;
3364 pa_scache_entry *sce = NULL;
3365 const char *name = NULL;
3366 pa_tagstruct *reply;
3367
3368 pa_native_connection_assert_ref(c);
3369 pa_assert(t);
3370
3371 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3372 (command != PA_COMMAND_GET_CLIENT_INFO &&
3373 command != PA_COMMAND_GET_MODULE_INFO &&
3374 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
3375 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
3376 pa_tagstruct_gets(t, &name) < 0) ||
3377 !pa_tagstruct_eof(t)) {
3378 protocol_error(c);
3379 return;
3380 }
3381
3382 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3383 CHECK_VALIDITY(c->pstream, !name ||
3384 (command == PA_COMMAND_GET_SINK_INFO &&
3385 pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SINK)) ||
3386 (command == PA_COMMAND_GET_SOURCE_INFO &&
3387 pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SOURCE)) ||
3388 pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3389 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3390 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3391 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3392
3393 if (command == PA_COMMAND_GET_SINK_INFO) {
3394 if (idx != PA_INVALID_INDEX)
3395 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3396 else
3397 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3398 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
3399 if (idx != PA_INVALID_INDEX)
3400 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3401 else
3402 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3403 } else if (command == PA_COMMAND_GET_CARD_INFO) {
3404 if (idx != PA_INVALID_INDEX)
3405 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
3406 else
3407 card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
3408 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
3409 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3410 else if (command == PA_COMMAND_GET_MODULE_INFO)
3411 module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3412 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
3413 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3414 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
3415 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3416 else {
3417 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
3418 if (idx != PA_INVALID_INDEX)
3419 sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
3420 else
3421 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
3422 }
3423
3424 if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
3425 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3426 return;
3427 }
3428
3429 reply = reply_new(tag);
3430 if (sink)
3431 sink_fill_tagstruct(c, reply, sink);
3432 else if (source)
3433 source_fill_tagstruct(c, reply, source);
3434 else if (client)
3435 client_fill_tagstruct(c, reply, client);
3436 else if (card)
3437 card_fill_tagstruct(c, reply, card);
3438 else if (module)
3439 module_fill_tagstruct(c, reply, module);
3440 else if (si)
3441 sink_input_fill_tagstruct(c, reply, si);
3442 else if (so)
3443 source_output_fill_tagstruct(c, reply, so);
3444 else
3445 scache_fill_tagstruct(c, reply, sce);
3446 pa_pstream_send_tagstruct(c->pstream, reply);
3447 }
3448
3449 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3450 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3451 pa_idxset *i;
3452 uint32_t idx;
3453 void *p;
3454 pa_tagstruct *reply;
3455
3456 pa_native_connection_assert_ref(c);
3457 pa_assert(t);
3458
3459 if (!pa_tagstruct_eof(t)) {
3460 protocol_error(c);
3461 return;
3462 }
3463
3464 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3465
3466 reply = reply_new(tag);
3467
3468 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3469 i = c->protocol->core->sinks;
3470 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3471 i = c->protocol->core->sources;
3472 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3473 i = c->protocol->core->clients;
3474 else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3475 i = c->protocol->core->cards;
3476 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3477 i = c->protocol->core->modules;
3478 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3479 i = c->protocol->core->sink_inputs;
3480 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3481 i = c->protocol->core->source_outputs;
3482 else {
3483 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3484 i = c->protocol->core->scache;
3485 }
3486
3487 if (i) {
3488 for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
3489 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3490 sink_fill_tagstruct(c, reply, p);
3491 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3492 source_fill_tagstruct(c, reply, p);
3493 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3494 client_fill_tagstruct(c, reply, p);
3495 else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3496 card_fill_tagstruct(c, reply, p);
3497 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3498 module_fill_tagstruct(c, reply, p);
3499 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3500 sink_input_fill_tagstruct(c, reply, p);
3501 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3502 source_output_fill_tagstruct(c, reply, p);
3503 else {
3504 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3505 scache_fill_tagstruct(c, reply, p);
3506 }
3507 }
3508 }
3509
3510 pa_pstream_send_tagstruct(c->pstream, reply);
3511 }
3512
3513 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3514 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3515 pa_tagstruct *reply;
3516 pa_sink *def_sink;
3517 pa_source *def_source;
3518 pa_sample_spec fixed_ss;
3519 char *h, *u;
3520
3521 pa_native_connection_assert_ref(c);
3522 pa_assert(t);
3523
3524 if (!pa_tagstruct_eof(t)) {
3525 protocol_error(c);
3526 return;
3527 }
3528
3529 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3530
3531 reply = reply_new(tag);
3532 pa_tagstruct_puts(reply, PACKAGE_NAME);
3533 pa_tagstruct_puts(reply, PACKAGE_VERSION);
3534
3535 u = pa_get_user_name_malloc();
3536 pa_tagstruct_puts(reply, u);
3537 pa_xfree(u);
3538
3539 h = pa_get_host_name_malloc();
3540 pa_tagstruct_puts(reply, h);
3541 pa_xfree(h);
3542
3543 fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
3544 pa_tagstruct_put_sample_spec(reply, &fixed_ss);
3545
3546 def_sink = pa_namereg_get_default_sink(c->protocol->core);
3547 pa_tagstruct_puts(reply, def_sink ? def_sink->name : NULL);
3548 def_source = pa_namereg_get_default_source(c->protocol->core);
3549 pa_tagstruct_puts(reply, def_source ? def_source->name : NULL);
3550
3551 pa_tagstruct_putu32(reply, c->protocol->core->cookie);
3552
3553 if (c->version >= 15)
3554 pa_tagstruct_put_channel_map(reply, &c->protocol->core->default_channel_map);
3555
3556 pa_pstream_send_tagstruct(c->pstream, reply);
3557 }
3558
3559 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
3560 pa_tagstruct *t;
3561 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3562
3563 pa_native_connection_assert_ref(c);
3564
3565 t = pa_tagstruct_new(NULL, 0);
3566 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
3567 pa_tagstruct_putu32(t, (uint32_t) -1);
3568 pa_tagstruct_putu32(t, e);
3569 pa_tagstruct_putu32(t, idx);
3570 pa_pstream_send_tagstruct(c->pstream, t);
3571 }
3572
3573 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3574 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3575 pa_subscription_mask_t m;
3576
3577 pa_native_connection_assert_ref(c);
3578 pa_assert(t);
3579
3580 if (pa_tagstruct_getu32(t, &m) < 0 ||
3581 !pa_tagstruct_eof(t)) {
3582 protocol_error(c);
3583 return;
3584 }
3585
3586 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3587 CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
3588
3589 if (c->subscription)
3590 pa_subscription_free(c->subscription);
3591
3592 if (m != 0) {
3593 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
3594 pa_assert(c->subscription);
3595 } else
3596 c->subscription = NULL;
3597
3598 pa_pstream_send_simple_ack(c->pstream, tag);
3599 }
3600
3601 static void command_set_volume(
3602 pa_pdispatch *pd,
3603 uint32_t command,
3604 uint32_t tag,
3605 pa_tagstruct *t,
3606 void *userdata) {
3607
3608 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3609 uint32_t idx;
3610 pa_cvolume volume;
3611 pa_sink *sink = NULL;
3612 pa_source *source = NULL;
3613 pa_sink_input *si = NULL;
3614 pa_source_output *so = NULL;
3615 const char *name = NULL;
3616 const char *client_name;
3617
3618 pa_native_connection_assert_ref(c);
3619 pa_assert(t);
3620
3621 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3622 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3623 (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3624 pa_tagstruct_get_cvolume(t, &volume) ||
3625 !pa_tagstruct_eof(t)) {
3626 protocol_error(c);
3627 return;
3628 }
3629
3630 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3631 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);
3632 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3633 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3634 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3635 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
3636
3637 switch (command) {
3638
3639 case PA_COMMAND_SET_SINK_VOLUME:
3640 if (idx != PA_INVALID_INDEX)
3641 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3642 else
3643 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3644 break;
3645
3646 case PA_COMMAND_SET_SOURCE_VOLUME:
3647 if (idx != PA_INVALID_INDEX)
3648 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3649 else
3650 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3651 break;
3652
3653 case PA_COMMAND_SET_SINK_INPUT_VOLUME:
3654 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3655 break;
3656
3657 case PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME:
3658 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3659 break;
3660
3661 default:
3662 pa_assert_not_reached();
3663 }
3664
3665 CHECK_VALIDITY(c->pstream, si || so || sink || source, tag, PA_ERR_NOENTITY);
3666
3667 client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3668
3669 if (sink) {
3670 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &sink->sample_spec), tag, PA_ERR_INVALID);
3671
3672 pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
3673 pa_sink_set_volume(sink, &volume, TRUE, TRUE);
3674 } else if (source) {
3675 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &source->sample_spec), tag, PA_ERR_INVALID);
3676
3677 pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
3678 pa_source_set_volume(source, &volume, TRUE, TRUE);
3679 } else if (si) {
3680 CHECK_VALIDITY(c->pstream, si->volume_writable, tag, PA_ERR_BADSTATE);
3681 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &si->sample_spec), tag, PA_ERR_INVALID);
3682
3683 pa_log_debug("Client %s changes volume of sink input %s.",
3684 client_name,
3685 pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3686 pa_sink_input_set_volume(si, &volume, TRUE, TRUE);
3687 } else if (so) {
3688 CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &so->sample_spec), tag, PA_ERR_INVALID);
3689
3690 pa_log_debug("Client %s changes volume of source output %s.",
3691 client_name,
3692 pa_strnull(pa_proplist_gets(so->proplist, PA_PROP_MEDIA_NAME)));
3693 pa_source_output_set_volume(so, &volume, TRUE, TRUE);
3694 }
3695
3696 pa_pstream_send_simple_ack(c->pstream, tag);
3697 }
3698
3699 static void command_set_mute(
3700 pa_pdispatch *pd,
3701 uint32_t command,
3702 uint32_t tag,
3703 pa_tagstruct *t,
3704 void *userdata) {
3705
3706 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3707 uint32_t idx;
3708 pa_bool_t mute;
3709 pa_sink *sink = NULL;
3710 pa_source *source = NULL;
3711 pa_sink_input *si = NULL;
3712 pa_source_output *so = NULL;
3713 const char *name = NULL, *client_name;
3714
3715 pa_native_connection_assert_ref(c);
3716 pa_assert(t);
3717
3718 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3719 (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3720 (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3721 pa_tagstruct_get_boolean(t, &mute) ||
3722 !pa_tagstruct_eof(t)) {
3723 protocol_error(c);
3724 return;
3725 }
3726
3727 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3728 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);
3729 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3730 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3731 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3732
3733 switch (command) {
3734
3735 case PA_COMMAND_SET_SINK_MUTE:
3736 if (idx != PA_INVALID_INDEX)
3737 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3738 else
3739 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3740
3741 break;
3742
3743 case PA_COMMAND_SET_SOURCE_MUTE:
3744 if (idx != PA_INVALID_INDEX)
3745 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3746 else
3747 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3748
3749 break;
3750
3751 case PA_COMMAND_SET_SINK_INPUT_MUTE:
3752 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3753 break;
3754
3755 case PA_COMMAND_SET_SOURCE_OUTPUT_MUTE:
3756 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3757 break;
3758
3759 default:
3760 pa_assert_not_reached();
3761 }
3762
3763 CHECK_VALIDITY(c->pstream, si || so || sink || source, tag, PA_ERR_NOENTITY);
3764
3765 client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3766
3767 if (sink) {
3768 pa_log_debug("Client %s changes mute of sink %s.", client_name, sink->name);
3769 pa_sink_set_mute(sink, mute, TRUE);
3770 } else if (source) {
3771 pa_log_debug("Client %s changes mute of source %s.", client_name, source->name);
3772 pa_source_set_mute(source, mute, TRUE);
3773 } else if (si) {
3774 pa_log_debug("Client %s changes mute of sink input %s.",
3775 client_name,
3776 pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3777 pa_sink_input_set_mute(si, mute, TRUE);
3778 } else if (so) {
3779 pa_log_debug("Client %s changes mute of source output %s.",
3780 client_name,
3781 pa_strnull(pa_proplist_gets(so->proplist, PA_PROP_MEDIA_NAME)));
3782 pa_source_output_set_mute(so, mute, TRUE);
3783 }
3784
3785 pa_pstream_send_simple_ack(c->pstream, tag);
3786 }
3787
3788 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3789 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3790 uint32_t idx;
3791 pa_bool_t b;
3792 playback_stream *s;
3793
3794 pa_native_connection_assert_ref(c);
3795 pa_assert(t);
3796
3797 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3798 pa_tagstruct_get_boolean(t, &b) < 0 ||
3799 !pa_tagstruct_eof(t)) {
3800 protocol_error(c);
3801 return;
3802 }
3803
3804 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3805 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3806 s = pa_idxset_get_by_index(c->output_streams, idx);
3807 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3808 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3809
3810 pa_sink_input_cork(s->sink_input, b);
3811
3812 if (b)
3813 s->is_underrun = TRUE;
3814
3815 pa_pstream_send_simple_ack(c->pstream, tag);
3816 }
3817
3818 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3819 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3820 uint32_t idx;
3821 playback_stream *s;
3822
3823 pa_native_connection_assert_ref(c);
3824 pa_assert(t);
3825
3826 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3827 !pa_tagstruct_eof(t)) {
3828 protocol_error(c);
3829 return;
3830 }
3831
3832 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3833 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3834 s = pa_idxset_get_by_index(c->output_streams, idx);
3835 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3836 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3837
3838 switch (command) {
3839 case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
3840 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
3841 break;
3842
3843 case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
3844 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
3845 break;
3846
3847 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
3848 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
3849 break;
3850
3851 default:
3852 pa_assert_not_reached();
3853 }
3854
3855 pa_pstream_send_simple_ack(c->pstream, tag);
3856 }
3857
3858 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3859 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3860 uint32_t idx;
3861 record_stream *s;
3862 pa_bool_t b;
3863
3864 pa_native_connection_assert_ref(c);
3865 pa_assert(t);
3866
3867 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3868 pa_tagstruct_get_boolean(t, &b) < 0 ||
3869 !pa_tagstruct_eof(t)) {
3870 protocol_error(c);
3871 return;
3872 }
3873
3874 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3875 s = pa_idxset_get_by_index(c->record_streams, idx);
3876 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3877
3878 pa_source_output_cork(s->source_output, b);
3879 pa_memblockq_prebuf_force(s->memblockq);
3880 pa_pstream_send_simple_ack(c->pstream, tag);
3881 }
3882
3883 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3884 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3885 uint32_t idx;
3886 record_stream *s;
3887
3888 pa_native_connection_assert_ref(c);
3889 pa_assert(t);
3890
3891 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3892 !pa_tagstruct_eof(t)) {
3893 protocol_error(c);
3894 return;
3895 }
3896
3897 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3898 s = pa_idxset_get_by_index(c->record_streams, idx);
3899 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3900
3901 pa_memblockq_flush_read(s->memblockq);
3902 pa_pstream_send_simple_ack(c->pstream, tag);
3903 }
3904
3905 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3906 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3907 uint32_t idx;
3908 pa_buffer_attr a;
3909 pa_tagstruct *reply;
3910
3911 pa_native_connection_assert_ref(c);
3912 pa_assert(t);
3913
3914 memset(&a, 0, sizeof(a));
3915
3916 if (pa_tagstruct_getu32(t, &idx) < 0) {
3917 protocol_error(c);
3918 return;
3919 }
3920
3921 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3922
3923 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
3924 playback_stream *s;
3925 pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3926
3927 s = pa_idxset_get_by_index(c->output_streams, idx);
3928 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3929 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3930
3931 if (pa_tagstruct_get(
3932 t,
3933 PA_TAG_U32, &a.maxlength,
3934 PA_TAG_U32, &a.tlength,
3935 PA_TAG_U32, &a.prebuf,
3936 PA_TAG_U32, &a.minreq,
3937 PA_TAG_INVALID) < 0 ||
3938 (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3939 (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3940 !pa_tagstruct_eof(t)) {
3941 protocol_error(c);
3942 return;
3943 }
3944
3945 s->adjust_latency = adjust_latency;
3946 s->early_requests = early_requests;
3947 s->buffer_attr_req = a;
3948
3949 fix_playback_buffer_attr(s);
3950 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);
3951
3952 reply = reply_new(tag);
3953 pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3954 pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
3955 pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
3956 pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
3957
3958 if (c->version >= 13)
3959 pa_tagstruct_put_usec(reply, s->configured_sink_latency);
3960
3961 } else {
3962 record_stream *s;
3963 pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3964 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
3965
3966 s = pa_idxset_get_by_index(c->record_streams, idx);
3967 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3968
3969 if (pa_tagstruct_get(
3970 t,
3971 PA_TAG_U32, &a.maxlength,
3972 PA_TAG_U32, &a.fragsize,
3973 PA_TAG_INVALID) < 0 ||
3974 (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3975 (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3976 !pa_tagstruct_eof(t)) {
3977 protocol_error(c);
3978 return;
3979 }
3980
3981 s->adjust_latency = adjust_latency;
3982 s->early_requests = early_requests;
3983 s->buffer_attr_req = a;
3984
3985 fix_record_buffer_attr_pre(s);
3986 pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
3987 pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
3988 fix_record_buffer_attr_post(s);
3989
3990 reply = reply_new(tag);
3991 pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3992 pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
3993
3994 if (c->version >= 13)
3995 pa_tagstruct_put_usec(reply, s->configured_source_latency);
3996 }
3997
3998 pa_pstream_send_tagstruct(c->pstream, reply);
3999 }
4000
4001 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4002 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4003 uint32_t idx;
4004 uint32_t rate;
4005
4006 pa_native_connection_assert_ref(c);
4007 pa_assert(t);
4008
4009 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4010 pa_tagstruct_getu32(t, &rate) < 0 ||
4011 !pa_tagstruct_eof(t)) {
4012 protocol_error(c);
4013 return;
4014 }
4015
4016 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4017 CHECK_VALIDITY(c->pstream, rate > 0 && rate <= PA_RATE_MAX, tag, PA_ERR_INVALID);
4018
4019 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
4020 playback_stream *s;
4021
4022 s = pa_idxset_get_by_index(c->output_streams, idx);
4023 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4024 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4025
4026 pa_sink_input_set_rate(s->sink_input, rate);
4027
4028 } else {
4029 record_stream *s;
4030 pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
4031
4032 s = pa_idxset_get_by_index(c->record_streams, idx);
4033 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4034
4035 pa_source_output_set_rate(s->source_output, rate);
4036 }
4037
4038 pa_pstream_send_simple_ack(c->pstream, tag);
4039 }
4040
4041 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4042 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4043 uint32_t idx;
4044 uint32_t mode;
4045 pa_proplist *p;
4046
4047 pa_native_connection_assert_ref(c);
4048 pa_assert(t);
4049
4050 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4051
4052 p = pa_proplist_new();
4053
4054 if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
4055
4056 if (pa_tagstruct_getu32(t, &mode) < 0 ||
4057 pa_tagstruct_get_proplist(t, p) < 0 ||
4058 !pa_tagstruct_eof(t)) {
4059 protocol_error(c);
4060 pa_proplist_free(p);
4061 return;
4062 }
4063
4064 } else {
4065
4066 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4067 pa_tagstruct_getu32(t, &mode) < 0 ||
4068 pa_tagstruct_get_proplist(t, p) < 0 ||
4069 !pa_tagstruct_eof(t)) {
4070 protocol_error(c);
4071 pa_proplist_free(p);
4072 return;
4073 }
4074 }
4075
4076 if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) {
4077 pa_proplist_free(p);
4078 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
4079 }
4080
4081 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
4082 playback_stream *s;
4083
4084 s = pa_idxset_get_by_index(c->output_streams, idx);
4085 if (!s || !playback_stream_isinstance(s)) {
4086 pa_proplist_free(p);
4087 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
4088 }
4089 pa_sink_input_update_proplist(s->sink_input, mode, p);
4090
4091 } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
4092 record_stream *s;
4093
4094 if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
4095 pa_proplist_free(p);
4096 CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
4097 }
4098 pa_source_output_update_proplist(s->source_output, mode, p);
4099
4100 } else {
4101 pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
4102
4103 pa_client_update_proplist(c->client, mode, p);
4104 }
4105
4106 pa_pstream_send_simple_ack(c->pstream, tag);
4107 pa_proplist_free(p);
4108 }
4109
4110 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4111 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4112 uint32_t idx;
4113 unsigned changed = 0;
4114 pa_proplist *p;
4115 pa_strlist *l = NULL;
4116
4117 pa_native_connection_assert_ref(c);
4118 pa_assert(t);
4119
4120 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4121
4122 if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
4123
4124 if (pa_tagstruct_getu32(t, &idx) < 0) {
4125 protocol_error(c);
4126 return;
4127 }
4128 }
4129
4130 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
4131 playback_stream *s;
4132
4133 s = pa_idxset_get_by_index(c->output_streams, idx);
4134 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4135 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4136
4137 p = s->sink_input->proplist;
4138
4139 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
4140 record_stream *s;
4141
4142 s = pa_idxset_get_by_index(c->record_streams, idx);
4143 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4144
4145 p = s->source_output->proplist;
4146 } else {
4147 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
4148
4149 p = c->client->proplist;
4150 }
4151
4152 for (;;) {
4153 const char *k;
4154
4155 if (pa_tagstruct_gets(t, &k) < 0) {
4156 protocol_error(c);
4157 pa_strlist_free(l);
4158 return;
4159 }
4160
4161 if (!k)
4162 break;
4163
4164 l = pa_strlist_prepend(l, k);
4165 }
4166
4167 if (!pa_tagstruct_eof(t)) {
4168 protocol_error(c);
4169 pa_strlist_free(l);
4170 return;
4171 }
4172
4173 for (;;) {
4174 char *z;
4175
4176 l = pa_strlist_pop(l, &z);
4177
4178 if (!z)
4179 break;
4180
4181 changed += (unsigned) (pa_proplist_unset(p, z) >= 0);
4182 pa_xfree(z);
4183 }
4184
4185 pa_pstream_send_simple_ack(c->pstream, tag);
4186
4187 if (changed) {
4188 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
4189 playback_stream *s;
4190
4191 s = pa_idxset_get_by_index(c->output_streams, idx);
4192 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
4193
4194 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
4195 record_stream *s;
4196
4197 s = pa_idxset_get_by_index(c->record_streams, idx);
4198 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
4199
4200 } else {
4201 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
4202 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
4203 }
4204 }
4205 }
4206
4207 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4208 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4209 const char *s;
4210
4211 pa_native_connection_assert_ref(c);
4212 pa_assert(t);
4213
4214 if (pa_tagstruct_gets(t, &s) < 0 ||
4215 !pa_tagstruct_eof(t)) {
4216 protocol_error(c);
4217 return;
4218 }
4219
4220 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4221 CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID);
4222
4223 if (command == PA_COMMAND_SET_DEFAULT_SOURCE) {
4224 pa_source *source;
4225
4226 source = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SOURCE);
4227 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4228
4229 pa_namereg_set_default_source(c->protocol->core, source);
4230 } else {
4231 pa_sink *sink;
4232 pa_assert(command == PA_COMMAND_SET_DEFAULT_SINK);
4233
4234 sink = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SINK);
4235 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4236
4237 pa_namereg_set_default_sink(c->protocol->core, sink);
4238 }
4239
4240 pa_pstream_send_simple_ack(c->pstream, tag);
4241 }
4242
4243 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4244 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4245 uint32_t idx;
4246 const char *name;
4247
4248 pa_native_connection_assert_ref(c);
4249 pa_assert(t);
4250
4251 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4252 pa_tagstruct_gets(t, &name) < 0 ||
4253 !pa_tagstruct_eof(t)) {
4254 protocol_error(c);
4255 return;
4256 }
4257
4258 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4259 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
4260
4261 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
4262 playback_stream *s;
4263
4264 s = pa_idxset_get_by_index(c->output_streams, idx);
4265 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4266 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
4267
4268 pa_sink_input_set_name(s->sink_input, name);
4269
4270 } else {
4271 record_stream *s;
4272 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
4273
4274 s = pa_idxset_get_by_index(c->record_streams, idx);
4275 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4276
4277 pa_source_output_set_name(s->source_output, name);
4278 }
4279
4280 pa_pstream_send_simple_ack(c->pstream, tag);
4281 }
4282
4283 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4284 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4285 uint32_t idx;
4286
4287 pa_native_connection_assert_ref(c);
4288 pa_assert(t);
4289
4290 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4291 !pa_tagstruct_eof(t)) {
4292 protocol_error(c);
4293 return;
4294 }
4295
4296 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4297
4298 if (command == PA_COMMAND_KILL_CLIENT) {
4299 pa_client *client;
4300
4301 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
4302 CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
4303
4304 pa_native_connection_ref(c);
4305 pa_client_kill(client);
4306
4307 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
4308 pa_sink_input *s;
4309
4310 s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4311 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4312
4313 pa_native_connection_ref(c);
4314 pa_sink_input_kill(s);
4315 } else {
4316 pa_source_output *s;
4317
4318 pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
4319
4320 s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4321 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4322
4323 pa_native_connection_ref(c);
4324 pa_source_output_kill(s);
4325 }
4326
4327 pa_pstream_send_simple_ack(c->pstream, tag);
4328 pa_native_connection_unref(c);
4329 }
4330
4331 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4332 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4333 pa_module *m;
4334 const char *name, *argument;
4335 pa_tagstruct *reply;
4336
4337 pa_native_connection_assert_ref(c);
4338 pa_assert(t);
4339
4340 if (pa_tagstruct_gets(t, &name) < 0 ||
4341 pa_tagstruct_gets(t, &argument) < 0 ||
4342 !pa_tagstruct_eof(t)) {
4343 protocol_error(c);
4344 return;
4345 }
4346
4347 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4348 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
4349 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
4350
4351 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
4352 pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
4353 return;
4354 }
4355
4356 reply = reply_new(tag);
4357 pa_tagstruct_putu32(reply, m->index);
4358 pa_pstream_send_tagstruct(c->pstream, reply);
4359 }
4360
4361 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4362 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4363 uint32_t idx;
4364 pa_module *m;
4365
4366 pa_native_connection_assert_ref(c);
4367 pa_assert(t);
4368
4369 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4370 !pa_tagstruct_eof(t)) {
4371 protocol_error(c);
4372 return;
4373 }
4374
4375 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4376 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4377 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
4378
4379 pa_module_unload_request(m, FALSE);
4380 pa_pstream_send_simple_ack(c->pstream, tag);
4381 }
4382
4383 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4384 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4385 uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
4386 const char *name_device = NULL;
4387
4388 pa_native_connection_assert_ref(c);
4389 pa_assert(t);
4390
4391 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4392 pa_tagstruct_getu32(t, &idx_device) < 0 ||
4393 pa_tagstruct_gets(t, &name_device) < 0 ||
4394 !pa_tagstruct_eof(t)) {
4395 protocol_error(c);
4396 return;
4397 }
4398
4399 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4400 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4401
4402 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);
4403 CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || name_device, tag, PA_ERR_INVALID);
4404 CHECK_VALIDITY(c->pstream, idx_device == PA_INVALID_INDEX || !name_device, tag, PA_ERR_INVALID);
4405 CHECK_VALIDITY(c->pstream, !name_device || idx_device == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4406
4407 if (command == PA_COMMAND_MOVE_SINK_INPUT) {
4408 pa_sink_input *si = NULL;
4409 pa_sink *sink = NULL;
4410
4411 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4412
4413 if (idx_device != PA_INVALID_INDEX)
4414 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
4415 else
4416 sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK);
4417
4418 CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
4419
4420 if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
4421 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4422 return;
4423 }
4424 } else {
4425 pa_source_output *so = NULL;
4426 pa_source *source;
4427
4428 pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
4429
4430 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4431
4432 if (idx_device != PA_INVALID_INDEX)
4433 source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
4434 else
4435 source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE);
4436
4437 CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
4438
4439 if (pa_source_output_move_to(so, source, TRUE) < 0) {
4440 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4441 return;
4442 }
4443 }
4444
4445 pa_pstream_send_simple_ack(c->pstream, tag);
4446 }
4447
4448 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4449 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4450 uint32_t idx = PA_INVALID_INDEX;
4451 const char *name = NULL;
4452 pa_bool_t b;
4453
4454 pa_native_connection_assert_ref(c);
4455 pa_assert(t);
4456
4457 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4458 pa_tagstruct_gets(t, &name) < 0 ||
4459 pa_tagstruct_get_boolean(t, &b) < 0 ||
4460 !pa_tagstruct_eof(t)) {
4461 protocol_error(c);
4462 return;
4463 }
4464
4465 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4466 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);
4467 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4468 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4469 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4470
4471 if (command == PA_COMMAND_SUSPEND_SINK) {
4472
4473 if (idx == PA_INVALID_INDEX && name && !*name) {
4474
4475 pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
4476
4477 if (pa_sink_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4478 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4479 return;
4480 }
4481 } else {
4482 pa_sink *sink = NULL;
4483
4484 if (idx != PA_INVALID_INDEX)
4485 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4486 else
4487 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4488
4489 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4490
4491 if (pa_sink_suspend(sink, b, PA_SUSPEND_USER) < 0) {
4492 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4493 return;
4494 }
4495 }
4496 } else {
4497
4498 pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
4499
4500 if (idx == PA_INVALID_INDEX && name && !*name) {
4501
4502 pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
4503
4504 if (pa_source_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4505 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4506 return;
4507 }
4508
4509 } else {
4510 pa_source *source;
4511
4512 if (idx != PA_INVALID_INDEX)
4513 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4514 else
4515 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4516
4517 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4518
4519 if (pa_source_suspend(source, b, PA_SUSPEND_USER) < 0) {
4520 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4521 return;
4522 }
4523 }
4524 }
4525
4526 pa_pstream_send_simple_ack(c->pstream, tag);
4527 }
4528
4529 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4530 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4531 uint32_t idx = PA_INVALID_INDEX;
4532 const char *name = NULL;
4533 pa_module *m;
4534 pa_native_protocol_ext_cb_t cb;
4535
4536 pa_native_connection_assert_ref(c);
4537 pa_assert(t);
4538
4539 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4540 pa_tagstruct_gets(t, &name) < 0) {
4541 protocol_error(c);
4542 return;
4543 }
4544
4545 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4546 CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
4547 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4548 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4549 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4550
4551 if (idx != PA_INVALID_INDEX)
4552 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4553 else {
4554 for (m = pa_idxset_first(c->protocol->core->modules, &idx); m; m = pa_idxset_next(c->protocol->core->modules, &idx))
4555 if (strcmp(name, m->name) == 0)
4556 break;
4557 }
4558
4559 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
4560 CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4561
4562 cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m);
4563 CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION);
4564
4565 if (cb(c->protocol, m, c, tag, t) < 0)
4566 protocol_error(c);
4567 }
4568
4569 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4570 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4571 uint32_t idx = PA_INVALID_INDEX;
4572 const char *name = NULL, *profile = NULL;
4573 pa_card *card = NULL;
4574 int ret;
4575
4576 pa_native_connection_assert_ref(c);
4577 pa_assert(t);
4578
4579 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4580 pa_tagstruct_gets(t, &name) < 0 ||
4581 pa_tagstruct_gets(t, &profile) < 0 ||
4582 !pa_tagstruct_eof(t)) {
4583 protocol_error(c);
4584 return;
4585 }
4586
4587 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4588 CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4589 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4590 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4591 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4592
4593 if (idx != PA_INVALID_INDEX)
4594 card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4595 else
4596 card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
4597
4598 CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4599
4600 if ((ret = pa_card_set_profile(card, profile, TRUE)) < 0) {
4601 pa_pstream_send_error(c->pstream, tag, -ret);
4602 return;
4603 }
4604
4605 pa_pstream_send_simple_ack(c->pstream, tag);
4606 }
4607
4608 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4609 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4610 uint32_t idx = PA_INVALID_INDEX;
4611 const char *name = NULL, *port = NULL;
4612 int ret;
4613
4614 pa_native_connection_assert_ref(c);
4615 pa_assert(t);
4616
4617 if (pa_tagstruct_getu32(t, &idx) < 0 ||
4618 pa_tagstruct_gets(t, &name) < 0 ||
4619 pa_tagstruct_gets(t, &port) < 0 ||
4620 !pa_tagstruct_eof(t)) {
4621 protocol_error(c);
4622 return;
4623 }
4624
4625 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4626 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);
4627 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4628 CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4629 CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4630
4631 if (command == PA_COMMAND_SET_SINK_PORT) {
4632 pa_sink *sink;
4633
4634 if (idx != PA_INVALID_INDEX)
4635 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4636 else
4637 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4638
4639 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4640
4641 if ((ret = pa_sink_set_port(sink, port, TRUE)) < 0) {
4642 pa_pstream_send_error(c->pstream, tag, -ret);
4643 return;
4644 }
4645 } else {
4646 pa_source *source;
4647
4648 pa_assert(command = PA_COMMAND_SET_SOURCE_PORT);
4649
4650 if (idx != PA_INVALID_INDEX)
4651 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4652 else
4653 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4654
4655 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4656
4657 if ((ret = pa_source_set_port(source, port, TRUE)) < 0) {
4658 pa_pstream_send_error(c->pstream, tag, -ret);
4659 return;
4660 }
4661 }
4662
4663 pa_pstream_send_simple_ack(c->pstream, tag);
4664 }
4665
4666 /*** pstream callbacks ***/
4667
4668 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
4669 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4670
4671 pa_assert(p);
4672 pa_assert(packet);
4673 pa_native_connection_assert_ref(c);
4674
4675 if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
4676 pa_log("invalid packet.");
4677 native_connection_unlink(c);
4678 }
4679 }
4680
4681 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) {
4682 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4683 output_stream *stream;
4684
4685 pa_assert(p);
4686 pa_assert(chunk);
4687 pa_native_connection_assert_ref(c);
4688
4689 if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
4690 pa_log_debug("Client sent block for invalid stream.");
4691 /* Ignoring */
4692 return;
4693 }
4694
4695 /* pa_log("got %lu bytes", (unsigned long) chunk->length); */
4696
4697 if (playback_stream_isinstance(stream)) {
4698 playback_stream *ps = PLAYBACK_STREAM(stream);
4699
4700 pa_atomic_inc(&ps->seek_or_post_in_queue);
4701 if (chunk->memblock) {
4702 if (seek != PA_SEEK_RELATIVE || offset != 0)
4703 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);
4704 else
4705 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
4706 } else
4707 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);
4708
4709 } else {
4710 upload_stream *u = UPLOAD_STREAM(stream);
4711 size_t l;
4712
4713 if (!u->memchunk.memblock) {
4714 if (u->length == chunk->length && chunk->memblock) {
4715 u->memchunk = *chunk;
4716 pa_memblock_ref(u->memchunk.memblock);
4717 u->length = 0;
4718 } else {
4719 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
4720 u->memchunk.index = u->memchunk.length = 0;
4721 }
4722 }
4723
4724 pa_assert(u->memchunk.memblock);
4725
4726 l = u->length;
4727 if (l > chunk->length)
4728 l = chunk->length;
4729
4730 if (l > 0) {
4731 void *dst;
4732 dst = pa_memblock_acquire(u->memchunk.memblock);
4733
4734 if (chunk->memblock) {
4735 void *src;
4736 src = pa_memblock_acquire(chunk->memblock);
4737
4738 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
4739 (uint8_t*) src + chunk->index, l);
4740
4741 pa_memblock_release(chunk->memblock);
4742 } else
4743 pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec);
4744
4745 pa_memblock_release(u->memchunk.memblock);
4746
4747 u->memchunk.length += l;
4748 u->length -= l;
4749 }
4750 }
4751 }
4752
4753 static void pstream_die_callback(pa_pstream *p, void *userdata) {
4754 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4755
4756 pa_assert(p);
4757 pa_native_connection_assert_ref(c);
4758
4759 native_connection_unlink(c);
4760 pa_log_info("Connection died.");
4761 }
4762
4763 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
4764 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4765
4766 pa_assert(p);
4767 pa_native_connection_assert_ref(c);
4768
4769 native_connection_send_memblock(c);
4770 }
4771
4772 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4773 pa_thread_mq *q;
4774
4775 if (!(q = pa_thread_mq_get()))
4776 pa_pstream_send_revoke(p, block_id);
4777 else
4778 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4779 }
4780
4781 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4782 pa_thread_mq *q;
4783
4784 if (!(q = pa_thread_mq_get()))
4785 pa_pstream_send_release(p, block_id);
4786 else
4787 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4788 }
4789
4790 /*** client callbacks ***/
4791
4792 static void client_kill_cb(pa_client *c) {
4793 pa_assert(c);
4794
4795 native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
4796 pa_log_info("Connection killed.");
4797 }
4798
4799 static void client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl) {
4800 pa_tagstruct *t;
4801 pa_native_connection *c;
4802
4803 pa_assert(client);
4804 c = PA_NATIVE_CONNECTION(client->userdata);
4805 pa_native_connection_assert_ref(c);
4806
4807 if (c->version < 15)
4808 return;
4809
4810 t = pa_tagstruct_new(NULL, 0);
4811 pa_tagstruct_putu32(t, PA_COMMAND_CLIENT_EVENT);
4812 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
4813 pa_tagstruct_puts(t, event);
4814 pa_tagstruct_put_proplist(t, pl);
4815 pa_pstream_send_tagstruct(c->pstream, t);
4816 }
4817
4818 /*** module entry points ***/
4819
4820 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) {
4821 pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4822
4823 pa_assert(m);
4824 pa_native_connection_assert_ref(c);
4825 pa_assert(c->auth_timeout_event == e);
4826
4827 if (!c->authorized) {
4828 native_connection_unlink(c);
4829 pa_log_info("Connection terminated due to authentication timeout.");
4830 }
4831 }
4832
4833 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
4834 pa_native_connection *c;
4835 char pname[128];
4836 pa_client *client;
4837 pa_client_new_data data;
4838
4839 pa_assert(p);
4840 pa_assert(io);
4841 pa_assert(o);
4842
4843 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
4844 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
4845 pa_iochannel_free(io);
4846 return;
4847 }
4848
4849 pa_client_new_data_init(&data);
4850 data.module = o->module;
4851 data.driver = __FILE__;
4852 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
4853 pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname);
4854 pa_proplist_sets(data.proplist, "native-protocol.peer", pname);
4855 client = pa_client_new(p->core, &data);
4856 pa_client_new_data_done(&data);
4857
4858 if (!client)
4859 return;
4860
4861 c = pa_msgobject_new(pa_native_connection);
4862 c->parent.parent.free = native_connection_free;
4863 c->parent.process_msg = native_connection_process_msg;
4864 c->protocol = p;
4865 c->options = pa_native_options_ref(o);
4866 c->authorized = FALSE;
4867
4868 if (o->auth_anonymous) {
4869 pa_log_info("Client authenticated anonymously.");
4870 c->authorized = TRUE;
4871 }
4872
4873 if (!c->authorized &&
4874 o->auth_ip_acl &&
4875 pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
4876
4877 pa_log_info("Client authenticated by IP ACL.");
4878 c->authorized = TRUE;
4879 }
4880
4881 if (!c->authorized)
4882 c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
4883 else
4884 c->auth_timeout_event = NULL;
4885
4886 c->is_local = pa_iochannel_socket_is_local(io);
4887 c->version = 8;
4888
4889 c->client = client;
4890 c->client->kill = client_kill_cb;
4891 c->client->send_event = client_send_event_cb;
4892 c->client->userdata = c;
4893
4894 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
4895 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
4896 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
4897 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
4898 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
4899 pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
4900 pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
4901
4902 c->pdispatch = pa_pdispatch_new(p->core->mainloop, TRUE, command_table, PA_COMMAND_MAX);
4903
4904 c->record_streams = pa_idxset_new(NULL, NULL);
4905 c->output_streams = pa_idxset_new(NULL, NULL);
4906
4907 c->rrobin_index = PA_IDXSET_INVALID;
4908 c->subscription = NULL;
4909
4910 pa_idxset_put(p->connections, c, NULL);
4911
4912 #ifdef HAVE_CREDS
4913 if (pa_iochannel_creds_supported(io))
4914 pa_iochannel_creds_enable(io);
4915 #endif
4916
4917 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
4918 }
4919
4920 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
4921 pa_native_connection *c;
4922 void *state = NULL;
4923
4924 pa_assert(p);
4925 pa_assert(m);
4926
4927 while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
4928 if (c->options->module == m)
4929 native_connection_unlink(c);
4930 }
4931
4932 static pa_native_protocol* native_protocol_new(pa_core *c) {
4933 pa_native_protocol *p;
4934 pa_native_hook_t h;
4935
4936 pa_assert(c);
4937
4938 p = pa_xnew(pa_native_protocol, 1);
4939 PA_REFCNT_INIT(p);
4940 p->core = c;
4941 p->connections = pa_idxset_new(NULL, NULL);
4942
4943 p->servers = NULL;
4944
4945 p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
4946
4947 for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4948 pa_hook_init(&p->hooks[h], p);
4949
4950 pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
4951
4952 return p;
4953 }
4954
4955 pa_native_protocol* pa_native_protocol_get(pa_core *c) {
4956 pa_native_protocol *p;
4957
4958 if ((p = pa_shared_get(c, "native-protocol")))
4959 return pa_native_protocol_ref(p);
4960
4961 return native_protocol_new(c);
4962 }
4963
4964 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
4965 pa_assert(p);
4966 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4967
4968 PA_REFCNT_INC(p);
4969
4970 return p;
4971 }
4972
4973 void pa_native_protocol_unref(pa_native_protocol *p) {
4974 pa_native_connection *c;
4975 pa_native_hook_t h;
4976
4977 pa_assert(p);
4978 pa_assert(PA_REFCNT_VALUE(p) >= 1);
4979
4980 if (PA_REFCNT_DEC(p) > 0)
4981 return;
4982
4983 while ((c = pa_idxset_first(p->connections, NULL)))
4984 native_connection_unlink(c);
4985
4986 pa_idxset_free(p->connections, NULL, NULL);
4987
4988 pa_strlist_free(p->servers);
4989
4990 for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4991 pa_hook_done(&p->hooks[h]);
4992
4993 pa_hashmap_free(p->extensions, NULL, NULL);
4994
4995 pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
4996
4997 pa_xfree(p);
4998 }
4999
5000 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name) {
5001 pa_assert(p);
5002 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5003 pa_assert(name);
5004
5005 p->servers = pa_strlist_prepend(p->servers, name);
5006
5007 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
5008 }
5009
5010 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
5011 pa_assert(p);
5012 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5013 pa_assert(name);
5014
5015 p->servers = pa_strlist_remove(p->servers, name);
5016
5017 pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
5018 }
5019
5020 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
5021 pa_assert(p);
5022 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5023
5024 return p->hooks;
5025 }
5026
5027 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
5028 pa_assert(p);
5029 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5030
5031 return p->servers;
5032 }
5033
5034 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb) {
5035 pa_assert(p);
5036 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5037 pa_assert(m);
5038 pa_assert(cb);
5039 pa_assert(!pa_hashmap_get(p->extensions, m));
5040
5041 pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) (unsigned long) cb) == 0);
5042 return 0;
5043 }
5044
5045 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
5046 pa_assert(p);
5047 pa_assert(PA_REFCNT_VALUE(p) >= 1);
5048 pa_assert(m);
5049
5050 pa_assert_se(pa_hashmap_remove(p->extensions, m));
5051 }
5052
5053 pa_native_options* pa_native_options_new(void) {
5054 pa_native_options *o;
5055
5056 o = pa_xnew0(pa_native_options, 1);
5057 PA_REFCNT_INIT(o);
5058
5059 return o;
5060 }
5061
5062 pa_native_options* pa_native_options_ref(pa_native_options *o) {
5063 pa_assert(o);
5064 pa_assert(PA_REFCNT_VALUE(o) >= 1);
5065
5066 PA_REFCNT_INC(o);
5067
5068 return o;
5069 }
5070
5071 void pa_native_options_unref(pa_native_options *o) {
5072 pa_assert(o);
5073 pa_assert(PA_REFCNT_VALUE(o) >= 1);
5074
5075 if (PA_REFCNT_DEC(o) > 0)
5076 return;
5077
5078 pa_xfree(o->auth_group);
5079
5080 if (o->auth_ip_acl)
5081 pa_ip_acl_free(o->auth_ip_acl);
5082
5083 if (o->auth_cookie)
5084 pa_auth_cookie_unref(o->auth_cookie);
5085
5086 pa_xfree(o);
5087 }
5088
5089 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
5090 pa_bool_t enabled;
5091 const char *acl;
5092
5093 pa_assert(o);
5094 pa_assert(PA_REFCNT_VALUE(o) >= 1);
5095 pa_assert(ma);
5096
5097 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
5098 pa_log("auth-anonymous= expects a boolean argument.");
5099 return -1;
5100 }
5101
5102 enabled = TRUE;
5103 if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &enabled) < 0) {
5104 pa_log("auth-group-enabled= expects a boolean argument.");
5105 return -1;
5106 }
5107
5108 pa_xfree(o->auth_group);
5109 o->auth_group = enabled ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
5110
5111 #ifndef HAVE_CREDS
5112 if (o->auth_group)
5113 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
5114 #endif
5115
5116 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
5117 pa_ip_acl *ipa;
5118
5119 if (!(ipa = pa_ip_acl_new(acl))) {
5120 pa_log("Failed to parse IP ACL '%s'", acl);
5121 return -1;
5122 }
5123
5124 if (o->auth_ip_acl)
5125 pa_ip_acl_free(o->auth_ip_acl);
5126
5127 o->auth_ip_acl = ipa;
5128 }
5129
5130 enabled = TRUE;
5131 if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
5132 pa_log("auth-cookie-enabled= expects a boolean argument.");
5133 return -1;
5134 }
5135
5136 if (o->auth_cookie)
5137 pa_auth_cookie_unref(o->auth_cookie);
5138
5139 if (enabled) {
5140 const char *cn;
5141
5142 /* The new name for this is 'auth-cookie', for compat reasons
5143 * we check the old name too */
5144 if (!(cn = pa_modargs_get_value(ma, "auth-cookie", NULL)))
5145 if (!(cn = pa_modargs_get_value(ma, "cookie", NULL)))
5146 cn = PA_NATIVE_COOKIE_FILE;
5147
5148 if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, PA_NATIVE_COOKIE_LENGTH)))
5149 return -1;
5150
5151 } else
5152 o->auth_cookie = NULL;
5153
5154 return 0;
5155 }
5156
5157 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
5158 pa_native_connection_assert_ref(c);
5159
5160 return c->pstream;
5161 }
5162
5163 pa_client* pa_native_connection_get_client(pa_native_connection *c) {
5164 pa_native_connection_assert_ref(c);
5165
5166 return c->client;
5167 }