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