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