]> code.delx.au - pulseaudio/blob - src/pulsecore/protocol-native.c
rename sink_input->rewind to process_rewind() and set_max_rewind to update_max_rewind()
[pulseaudio] / src / pulsecore / protocol-native.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33
34 #include <pulse/timeval.h>
35 #include <pulse/version.h>
36 #include <pulse/utf8.h>
37 #include <pulse/util.h>
38 #include <pulse/xmalloc.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/authkey.h>
50 #include <pulsecore/namereg.h>
51 #include <pulsecore/core-scache.h>
52 #include <pulsecore/core-subscribe.h>
53 #include <pulsecore/log.h>
54 #include <pulsecore/autoload.h>
55 #include <pulsecore/authkey-prop.h>
56 #include <pulsecore/strlist.h>
57 #include <pulsecore/props.h>
58 #include <pulsecore/sample-util.h>
59 #include <pulsecore/llist.h>
60 #include <pulsecore/creds.h>
61 #include <pulsecore/core-util.h>
62 #include <pulsecore/ipacl.h>
63 #include <pulsecore/thread-mq.h>
64
65 #include "protocol-native.h"
66
67 /* Kick a client if it doesn't authenticate within this time */
68 #define AUTH_TIMEOUT 60
69
70 /* Don't accept more connection than this */
71 #define MAX_CONNECTIONS 64
72
73 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
74 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
75 #define DEFAULT_PROCESS_MSEC 20 /* 20ms */
76 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
77
78 typedef struct connection connection;
79 struct pa_protocol_native;
80
81 typedef struct record_stream {
82 pa_msgobject parent;
83
84 connection *connection;
85 uint32_t index;
86
87 pa_source_output *source_output;
88 pa_memblockq *memblockq;
89 size_t fragment_size;
90 pa_usec_t source_latency;
91 } record_stream;
92
93 typedef struct output_stream {
94 pa_msgobject parent;
95 } output_stream;
96
97 typedef struct playback_stream {
98 output_stream parent;
99
100 connection *connection;
101 uint32_t index;
102
103 pa_sink_input *sink_input;
104 pa_memblockq *memblockq;
105 pa_bool_t drain_request;
106 uint32_t drain_tag;
107 uint32_t syncid;
108 uint64_t underrun; /* length of underrun */
109
110 pa_atomic_t missing;
111 size_t minreq;
112 pa_usec_t sink_latency;
113
114 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
115 int64_t read_index, write_index;
116 size_t render_memblockq_length;
117 } playback_stream;
118
119 typedef struct upload_stream {
120 output_stream parent;
121
122 connection *connection;
123 uint32_t index;
124
125 pa_memchunk memchunk;
126 size_t length;
127 char *name;
128 pa_sample_spec sample_spec;
129 pa_channel_map channel_map;
130 pa_proplist *proplist;
131 } upload_stream;
132
133 struct connection {
134 pa_msgobject parent;
135
136 pa_bool_t authorized;
137 uint32_t version;
138 pa_protocol_native *protocol;
139 pa_client *client;
140 pa_pstream *pstream;
141 pa_pdispatch *pdispatch;
142 pa_idxset *record_streams, *output_streams;
143 uint32_t rrobin_index;
144 pa_subscription *subscription;
145 pa_time_event *auth_timeout_event;
146 };
147
148 PA_DECLARE_CLASS(record_stream);
149 #define RECORD_STREAM(o) (record_stream_cast(o))
150 static PA_DEFINE_CHECK_TYPE(record_stream, pa_msgobject);
151
152 PA_DECLARE_CLASS(output_stream);
153 #define OUTPUT_STREAM(o) (output_stream_cast(o))
154 static PA_DEFINE_CHECK_TYPE(output_stream, pa_msgobject);
155
156 PA_DECLARE_CLASS(playback_stream);
157 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
158 static PA_DEFINE_CHECK_TYPE(playback_stream, output_stream);
159
160 PA_DECLARE_CLASS(upload_stream);
161 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
162 static PA_DEFINE_CHECK_TYPE(upload_stream, output_stream);
163
164 PA_DECLARE_CLASS(connection);
165 #define CONNECTION(o) (connection_cast(o))
166 static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
167
168 struct pa_protocol_native {
169 pa_module *module;
170 pa_core *core;
171 pa_bool_t public;
172 pa_socket_server *server;
173 pa_idxset *connections;
174 uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
175 pa_bool_t auth_cookie_in_property;
176 #ifdef HAVE_CREDS
177 char *auth_group;
178 #endif
179 pa_ip_acl *auth_ip_acl;
180 };
181
182 enum {
183 SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
184 SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */
185 SINK_INPUT_MESSAGE_FLUSH,
186 SINK_INPUT_MESSAGE_TRIGGER,
187 SINK_INPUT_MESSAGE_SEEK,
188 SINK_INPUT_MESSAGE_PREBUF_FORCE,
189 SINK_INPUT_MESSAGE_UPDATE_LATENCY
190 };
191
192 enum {
193 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, /* data requested from sink input from the main loop */
194 PLAYBACK_STREAM_MESSAGE_UNDERFLOW,
195 PLAYBACK_STREAM_MESSAGE_OVERFLOW,
196 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
197 };
198
199 enum {
200 RECORD_STREAM_MESSAGE_POST_DATA /* data from source output to main loop */
201 };
202
203 enum {
204 CONNECTION_MESSAGE_RELEASE,
205 CONNECTION_MESSAGE_REVOKE
206 };
207
208 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
209 static void sink_input_kill_cb(pa_sink_input *i);
210 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
211 static void sink_input_moved_cb(pa_sink_input *i);
212 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
213 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
214
215
216 static void send_memblock(connection *c);
217 static void request_bytes(struct playback_stream*s);
218
219 static void source_output_kill_cb(pa_source_output *o);
220 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
221 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend);
222 static void source_output_moved_cb(pa_source_output *o);
223 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
224
225 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
226
227 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
228 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
229 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
230 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
231 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
232 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
233 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
234 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
235 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
236 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
237 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
238 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
239 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
240 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
241 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
242 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
243 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
244 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
245 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
246 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
247 static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
248 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
249 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
250 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
251 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
252 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
253 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
254 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
255 static void command_add_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
256 static void command_remove_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
257 static void command_get_autoload_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
258 static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
259 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
260 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
261 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
262 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
263 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
264 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
265 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
266 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
267
268 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
269 [PA_COMMAND_ERROR] = NULL,
270 [PA_COMMAND_TIMEOUT] = NULL,
271 [PA_COMMAND_REPLY] = NULL,
272 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
273 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
274 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
275 [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
276 [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
277 [PA_COMMAND_AUTH] = command_auth,
278 [PA_COMMAND_REQUEST] = NULL,
279 [PA_COMMAND_EXIT] = command_exit,
280 [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
281 [PA_COMMAND_LOOKUP_SINK] = command_lookup,
282 [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
283 [PA_COMMAND_STAT] = command_stat,
284 [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
285 [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
286 [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
287 [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
288 [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
289 [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
290 [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
291 [PA_COMMAND_GET_SINK_INFO] = command_get_info,
292 [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
293 [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
294 [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
295 [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
296 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
297 [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
298 [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
299 [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
300 [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
301 [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
302 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
303 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
304 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
305 [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
306 [PA_COMMAND_SUBSCRIBE] = command_subscribe,
307
308 [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
309 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
310 [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
311
312 [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
313 [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
314 [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
315
316 [PA_COMMAND_SUSPEND_SINK] = command_suspend,
317 [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
318
319 [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
320 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
321 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
322 [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
323
324 [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
325 [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
326
327 [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
328 [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
329 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
330 [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
331 [PA_COMMAND_KILL_CLIENT] = command_kill,
332 [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
333 [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
334 [PA_COMMAND_LOAD_MODULE] = command_load_module,
335 [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
336 [PA_COMMAND_GET_AUTOLOAD_INFO] = command_get_autoload_info,
337 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = command_get_autoload_info_list,
338 [PA_COMMAND_ADD_AUTOLOAD] = command_add_autoload,
339 [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload,
340
341 [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
342 [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream,
343
344 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
345 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
346
347 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
348 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
349
350 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = command_update_proplist,
351 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = command_update_proplist,
352 [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = command_update_proplist,
353
354 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = command_remove_proplist,
355 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
356 [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
357 };
358
359 /* structure management */
360
361 static void upload_stream_unlink(upload_stream *s) {
362 pa_assert(s);
363
364 if (!s->connection)
365 return;
366
367 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
368 s->connection = NULL;
369 upload_stream_unref(s);
370 }
371
372 static void upload_stream_free(pa_object *o) {
373 upload_stream *s = UPLOAD_STREAM(o);
374 pa_assert(s);
375
376 upload_stream_unlink(s);
377
378 pa_xfree(s->name);
379
380 if (s->proplist)
381 pa_proplist_free(s->proplist);
382
383 if (s->memchunk.memblock)
384 pa_memblock_unref(s->memchunk.memblock);
385
386 pa_xfree(s);
387 }
388
389 static upload_stream* upload_stream_new(
390 connection *c,
391 const pa_sample_spec *ss,
392 const pa_channel_map *map,
393 const char *name,
394 size_t length,
395 pa_proplist *p) {
396
397 upload_stream *s;
398
399 pa_assert(c);
400 pa_assert(ss);
401 pa_assert(name);
402 pa_assert(length > 0);
403 pa_assert(p);
404
405 s = pa_msgobject_new(upload_stream);
406 s->parent.parent.parent.free = upload_stream_free;
407 s->connection = c;
408 s->sample_spec = *ss;
409 s->channel_map = *map;
410 s->name = pa_xstrdup(name);
411 pa_memchunk_reset(&s->memchunk);
412 s->length = length;
413 s->proplist = pa_proplist_copy(p);
414 pa_proplist_update(s->proplist, PA_UPDATE_MERGE, c->client->proplist);
415
416 pa_idxset_put(c->output_streams, s, &s->index);
417
418 return s;
419 }
420
421 static void record_stream_unlink(record_stream *s) {
422 pa_assert(s);
423
424 if (!s->connection)
425 return;
426
427 if (s->source_output) {
428 pa_source_output_unlink(s->source_output);
429 pa_source_output_unref(s->source_output);
430 s->source_output = NULL;
431 }
432
433 pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
434 s->connection = NULL;
435 record_stream_unref(s);
436 }
437
438 static void record_stream_free(pa_object *o) {
439 record_stream *s = RECORD_STREAM(o);
440 pa_assert(s);
441
442 record_stream_unlink(s);
443
444 pa_memblockq_free(s->memblockq);
445 pa_xfree(s);
446 }
447
448 static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
449 record_stream *s = RECORD_STREAM(o);
450 record_stream_assert_ref(s);
451
452 if (!s->connection)
453 return -1;
454
455 switch (code) {
456
457 case RECORD_STREAM_MESSAGE_POST_DATA:
458
459 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
460 /* pa_log_warn("Failed to push data into output queue."); */
461 return -1;
462 }
463
464 if (!pa_pstream_is_pending(s->connection->pstream))
465 send_memblock(s->connection);
466
467 break;
468 }
469
470 return 0;
471 }
472
473 static record_stream* record_stream_new(
474 connection *c,
475 pa_source *source,
476 pa_sample_spec *ss,
477 pa_channel_map *map,
478 uint32_t *maxlength,
479 uint32_t *fragsize,
480 pa_source_output_flags_t flags,
481 pa_proplist *p,
482 pa_bool_t adjust_latency) {
483
484 record_stream *s;
485 pa_source_output *source_output;
486 size_t base;
487 pa_source_output_new_data data;
488
489 pa_assert(c);
490 pa_assert(ss);
491 pa_assert(maxlength);
492 pa_assert(p);
493
494 pa_source_output_new_data_init(&data);
495
496 pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
497 pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
498 data.driver = __FILE__;
499 data.module = c->protocol->module;
500 data.client = c->client;
501 data.source = source;
502 pa_source_output_new_data_set_sample_spec(&data, ss);
503 pa_source_output_new_data_set_channel_map(&data, map);
504
505 source_output = pa_source_output_new(c->protocol->core, &data, flags);
506
507 pa_source_output_new_data_done(&data);
508
509 if (!source_output)
510 return NULL;
511
512 s = pa_msgobject_new(record_stream);
513 s->parent.parent.free = record_stream_free;
514 s->parent.process_msg = record_stream_process_msg;
515 s->connection = c;
516 s->source_output = source_output;
517
518 s->source_output->push = source_output_push_cb;
519 s->source_output->kill = source_output_kill_cb;
520 s->source_output->get_latency = source_output_get_latency_cb;
521 s->source_output->moved = source_output_moved_cb;
522 s->source_output->suspend = source_output_suspend_cb;
523 s->source_output->userdata = s;
524
525 if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
526 *maxlength = MAX_MEMBLOCKQ_LENGTH;
527 if (*fragsize <= 0)
528 *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &source_output->sample_spec);
529
530 if (adjust_latency) {
531 pa_usec_t fragsize_usec;
532
533 /* So, the user asked us to adjust the latency according to
534 * the what the source can provide. Half the latency will be
535 * spent on the hw buffer, half of it in the async buffer
536 * queue we maintain for each client. */
537
538 fragsize_usec = pa_bytes_to_usec(*fragsize, &source_output->sample_spec);
539
540 s->source_latency = pa_source_output_set_requested_latency(source_output, fragsize_usec/2);
541
542 if (fragsize_usec >= s->source_latency*2)
543 fragsize_usec -= s->source_latency;
544 else
545 fragsize_usec = s->source_latency;
546
547 *fragsize = pa_usec_to_bytes(fragsize_usec, &source_output->sample_spec);
548 }
549
550 s->memblockq = pa_memblockq_new(
551 0,
552 *maxlength,
553 0,
554 base = pa_frame_size(&source_output->sample_spec),
555 1,
556 0,
557 0,
558 NULL);
559
560 *maxlength = pa_memblockq_get_maxlength(s->memblockq);
561
562 s->fragment_size = (*fragsize/base)*base;
563 if (s->fragment_size <= 0)
564 s->fragment_size = base;
565
566 if (s->fragment_size > *maxlength)
567 s->fragment_size = *maxlength;
568
569 *fragsize = s->fragment_size;
570
571 *ss = s->source_output->sample_spec;
572 *map = s->source_output->channel_map;
573
574 pa_idxset_put(c->record_streams, s, &s->index);
575
576 pa_source_output_put(s->source_output);
577 return s;
578 }
579
580 static void playback_stream_unlink(playback_stream *s) {
581 pa_assert(s);
582
583 if (!s->connection)
584 return;
585
586 if (s->sink_input) {
587 pa_sink_input_unlink(s->sink_input);
588 pa_sink_input_unref(s->sink_input);
589 s->sink_input = NULL;
590 }
591
592 if (s->drain_request)
593 pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
594
595 pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
596 s->connection = NULL;
597 playback_stream_unref(s);
598 }
599
600 static void playback_stream_free(pa_object* o) {
601 playback_stream *s = PLAYBACK_STREAM(o);
602 pa_assert(s);
603
604 playback_stream_unlink(s);
605
606 pa_memblockq_free(s->memblockq);
607 pa_xfree(s);
608 }
609
610 static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
611 playback_stream *s = PLAYBACK_STREAM(o);
612 playback_stream_assert_ref(s);
613
614 if (!s->connection)
615 return -1;
616
617 switch (code) {
618 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
619 pa_tagstruct *t;
620 uint32_t l = 0;
621
622 for (;;) {
623 if ((l = pa_atomic_load(&s->missing)) <= 0)
624 break;
625
626 if (pa_atomic_cmpxchg(&s->missing, l, 0))
627 break;
628 }
629
630 if (l <= 0)
631 break;
632
633 t = pa_tagstruct_new(NULL, 0);
634 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
635 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
636 pa_tagstruct_putu32(t, s->index);
637 pa_tagstruct_putu32(t, l);
638 pa_pstream_send_tagstruct(s->connection->pstream, t);
639
640 /* pa_log("Requesting %lu bytes", (unsigned long) l); */
641 break;
642 }
643
644 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
645 pa_tagstruct *t;
646
647 /* Report that we're empty */
648 t = pa_tagstruct_new(NULL, 0);
649 pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
650 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
651 pa_tagstruct_putu32(t, s->index);
652 pa_pstream_send_tagstruct(s->connection->pstream, t);
653 break;
654 }
655
656 case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
657 pa_tagstruct *t;
658
659 /* Notify the user we're overflowed*/
660 t = pa_tagstruct_new(NULL, 0);
661 pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
662 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
663 pa_tagstruct_putu32(t, s->index);
664 pa_pstream_send_tagstruct(s->connection->pstream, t);
665 break;
666 }
667
668 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
669 pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
670 break;
671
672 }
673
674 return 0;
675 }
676
677 static playback_stream* playback_stream_new(
678 connection *c,
679 pa_sink *sink,
680 pa_sample_spec *ss,
681 pa_channel_map *map,
682 uint32_t *maxlength,
683 uint32_t *tlength,
684 uint32_t *prebuf,
685 uint32_t *minreq,
686 pa_cvolume *volume,
687 pa_bool_t muted,
688 uint32_t syncid,
689 uint32_t *missing,
690 pa_sink_input_flags_t flags,
691 pa_proplist *p,
692 pa_bool_t adjust_latency) {
693
694 playback_stream *s, *ssync;
695 pa_sink_input *sink_input;
696 pa_memchunk silence;
697 uint32_t idx;
698 int64_t start_index;
699 pa_sink_input_new_data data;
700 pa_usec_t tlength_usec, minreq_usec, sink_usec;
701 size_t frame_size;
702
703 pa_assert(c);
704 pa_assert(ss);
705 pa_assert(maxlength);
706 pa_assert(tlength);
707 pa_assert(prebuf);
708 pa_assert(minreq);
709 pa_assert(volume);
710 pa_assert(missing);
711 pa_assert(p);
712
713 /* Find syncid group */
714 for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
715
716 if (!playback_stream_isinstance(ssync))
717 continue;
718
719 if (ssync->syncid == syncid)
720 break;
721 }
722
723 /* Synced streams must connect to the same sink */
724 if (ssync) {
725
726 if (!sink)
727 sink = ssync->sink_input->sink;
728 else if (sink != ssync->sink_input->sink)
729 return NULL;
730 }
731
732 pa_sink_input_new_data_init(&data);
733
734 pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
735 pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
736 data.driver = __FILE__;
737 data.module = c->protocol->module;
738 data.client = c->client;
739 data.sink = sink;
740 pa_sink_input_new_data_set_sample_spec(&data, ss);
741 pa_sink_input_new_data_set_channel_map(&data, map);
742 pa_sink_input_new_data_set_volume(&data, volume);
743 pa_sink_input_new_data_set_muted(&data, muted);
744 data.sync_base = ssync ? ssync->sink_input : NULL;
745
746 sink_input = pa_sink_input_new(c->protocol->core, &data, flags);
747
748 pa_sink_input_new_data_done(&data);
749
750 if (!sink_input)
751 return NULL;
752
753 s = pa_msgobject_new(playback_stream);
754 s->parent.parent.parent.free = playback_stream_free;
755 s->parent.parent.process_msg = playback_stream_process_msg;
756 s->connection = c;
757 s->syncid = syncid;
758 s->sink_input = sink_input;
759 s->underrun = (uint64_t) -1;
760
761 s->sink_input->parent.process_msg = sink_input_process_msg;
762 s->sink_input->pop = sink_input_pop_cb;
763 s->sink_input->process_rewind = sink_input_process_rewind_cb;
764 s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
765 s->sink_input->kill = sink_input_kill_cb;
766 s->sink_input->moved = sink_input_moved_cb;
767 s->sink_input->suspend = sink_input_suspend_cb;
768 s->sink_input->userdata = s;
769
770 start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
771
772 if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
773 *maxlength = MAX_MEMBLOCKQ_LENGTH;
774 if (*tlength <= 0)
775 *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &sink_input->sample_spec);
776 if (*minreq <= 0)
777 *minreq = pa_usec_to_bytes(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &sink_input->sample_spec);
778
779 frame_size = pa_frame_size(&sink_input->sample_spec);
780 if (*minreq <= 0)
781 *minreq = frame_size;
782 if (*tlength < *minreq+frame_size)
783 *tlength = *minreq+frame_size;
784
785 tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
786 minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
787
788 if (adjust_latency) {
789
790 /* So, the user asked us to adjust the latency of the stream
791 * buffer according to the what the sink can provide. The
792 * tlength passed in shall be the overall latency. Roughly
793 * half the latency will be spent on the hw buffer, the other
794 * half of it in the async buffer queue we maintain for each
795 * client. In between we'll have a safety space of size
796 * minreq.*/
797
798 sink_usec = (tlength_usec-minreq_usec)/2;
799
800 } else {
801
802 /* Ok, the user didn't ask us to adjust the latency, but we
803 * still need to make sure that the parameters from the user
804 * do make sense. */
805
806 sink_usec = tlength_usec - minreq_usec;
807 }
808
809 s->sink_latency = pa_sink_input_set_requested_latency(sink_input, sink_usec);
810
811 if (adjust_latency) {
812 /* Ok, we didn't necessarily get what we were asking for, so
813 * let's subtract from what we asked for for the remaining
814 * buffer space */
815
816 if (tlength_usec >= s->sink_latency)
817 tlength_usec -= s->sink_latency;
818 }
819
820 if (tlength_usec < s->sink_latency + minreq_usec)
821 tlength_usec = s->sink_latency + minreq_usec;
822
823 *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
824 *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
825
826 if (*minreq <= 0) {
827 *minreq = frame_size;
828 *tlength += frame_size;
829 }
830
831 if (*tlength <= *minreq)
832 *tlength = *minreq + frame_size;
833
834 if (*prebuf <= 0)
835 *prebuf = *tlength;
836
837 pa_sink_input_get_silence(sink_input, &silence);
838
839 s->memblockq = pa_memblockq_new(
840 start_index,
841 *maxlength,
842 *tlength,
843 pa_frame_size(&sink_input->sample_spec),
844 *prebuf,
845 *minreq,
846 0,
847 &silence);
848
849 pa_memblock_unref(silence.memblock);
850
851 *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
852 *tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq);
853 *prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq);
854 *minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq);
855 *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
856
857 *ss = s->sink_input->sample_spec;
858 *map = s->sink_input->channel_map;
859
860 s->minreq = pa_memblockq_get_minreq(s->memblockq);
861 pa_atomic_store(&s->missing, 0);
862 s->drain_request = FALSE;
863
864 pa_idxset_put(c->output_streams, s, &s->index);
865
866 pa_sink_input_put(s->sink_input);
867 return s;
868 }
869
870 static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
871 connection *c = CONNECTION(o);
872 connection_assert_ref(c);
873
874 if (!c->protocol)
875 return -1;
876
877 switch (code) {
878
879 case CONNECTION_MESSAGE_REVOKE:
880 pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
881 break;
882
883 case CONNECTION_MESSAGE_RELEASE:
884 pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
885 break;
886 }
887
888 return 0;
889 }
890
891 static void connection_unlink(connection *c) {
892 record_stream *r;
893 output_stream *o;
894
895 pa_assert(c);
896
897 if (!c->protocol)
898 return;
899
900 while ((r = pa_idxset_first(c->record_streams, NULL)))
901 record_stream_unlink(r);
902
903 while ((o = pa_idxset_first(c->output_streams, NULL)))
904 if (playback_stream_isinstance(o))
905 playback_stream_unlink(PLAYBACK_STREAM(o));
906 else
907 upload_stream_unlink(UPLOAD_STREAM(o));
908
909 if (c->subscription)
910 pa_subscription_free(c->subscription);
911
912 if (c->pstream)
913 pa_pstream_unlink(c->pstream);
914
915 if (c->auth_timeout_event) {
916 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
917 c->auth_timeout_event = NULL;
918 }
919
920 pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
921 c->protocol = NULL;
922 connection_unref(c);
923 }
924
925 static void connection_free(pa_object *o) {
926 connection *c = CONNECTION(o);
927
928 pa_assert(c);
929
930 connection_unlink(c);
931
932 pa_idxset_free(c->record_streams, NULL, NULL);
933 pa_idxset_free(c->output_streams, NULL, NULL);
934
935 pa_pdispatch_unref(c->pdispatch);
936 pa_pstream_unref(c->pstream);
937 pa_client_free(c->client);
938
939 pa_xfree(c);
940 }
941
942 /* Called from thread context */
943 static void request_bytes(playback_stream *s) {
944 size_t m, previous_missing;
945
946 playback_stream_assert_ref(s);
947
948 m = pa_memblockq_pop_missing(s->memblockq);
949
950 if (m <= 0)
951 return;
952
953 /* pa_log("request_bytes(%lu)", (unsigned long) m); */
954
955 previous_missing = pa_atomic_add(&s->missing, m);
956
957 if (pa_memblockq_prebuf_active(s->memblockq) ||
958 (previous_missing < s->minreq && previous_missing+m >= s->minreq)) {
959 pa_assert(pa_thread_mq_get());
960 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
961 }
962 }
963
964 static void send_memblock(connection *c) {
965 uint32_t start;
966 record_stream *r;
967
968 start = PA_IDXSET_INVALID;
969 for (;;) {
970 pa_memchunk chunk;
971
972 if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
973 return;
974
975 if (start == PA_IDXSET_INVALID)
976 start = c->rrobin_index;
977 else if (start == c->rrobin_index)
978 return;
979
980 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
981 pa_memchunk schunk = chunk;
982
983 if (schunk.length > r->fragment_size)
984 schunk.length = r->fragment_size;
985
986 pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
987
988 pa_memblockq_drop(r->memblockq, schunk.length);
989 pa_memblock_unref(schunk.memblock);
990
991 return;
992 }
993 }
994 }
995
996 static void send_playback_stream_killed(playback_stream *p) {
997 pa_tagstruct *t;
998 playback_stream_assert_ref(p);
999
1000 t = pa_tagstruct_new(NULL, 0);
1001 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
1002 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1003 pa_tagstruct_putu32(t, p->index);
1004 pa_pstream_send_tagstruct(p->connection->pstream, t);
1005 }
1006
1007 static void send_record_stream_killed(record_stream *r) {
1008 pa_tagstruct *t;
1009 record_stream_assert_ref(r);
1010
1011 t = pa_tagstruct_new(NULL, 0);
1012 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
1013 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1014 pa_tagstruct_putu32(t, r->index);
1015 pa_pstream_send_tagstruct(r->connection->pstream, t);
1016 }
1017
1018 /*** sink input callbacks ***/
1019
1020 static void handle_seek(playback_stream *s, int64_t indexw) {
1021 playback_stream_assert_ref(s);
1022
1023 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->underrun, pa_memblockq_is_readable(s->memblockq)); */
1024
1025 if (s->underrun != 0) {
1026
1027 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1028
1029 if (pa_memblockq_is_readable(s->memblockq)) {
1030
1031 size_t u = pa_memblockq_get_length(s->memblockq);
1032
1033 if (u >= s->underrun)
1034 u = s->underrun;
1035
1036 pa_log("yeah! ready to rock");
1037
1038 /* We just ended an underrun, let's ask the sink
1039 * to rewrite */
1040 s->sink_input->thread_info.ignore_rewind = TRUE;
1041 pa_sink_input_request_rewind(s->sink_input, u, TRUE);
1042 }
1043
1044 } else {
1045 int64_t indexr;
1046
1047 indexr = pa_memblockq_get_read_index(s->memblockq);
1048
1049 if (indexw < indexr)
1050 /* OK, the sink already asked for this data, so
1051 * let's have it usk us again */
1052
1053 pa_sink_input_request_rewind(s->sink_input, indexr - indexw, FALSE);
1054 }
1055
1056 request_bytes(s);
1057 }
1058
1059 /* Called from thread context */
1060 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1061 pa_sink_input *i = PA_SINK_INPUT(o);
1062 playback_stream *s;
1063
1064 pa_sink_input_assert_ref(i);
1065 s = PLAYBACK_STREAM(i->userdata);
1066 playback_stream_assert_ref(s);
1067
1068 switch (code) {
1069
1070 case SINK_INPUT_MESSAGE_SEEK: {
1071 int64_t windex;
1072
1073 windex = pa_memblockq_get_write_index(s->memblockq);
1074 pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata));
1075
1076 handle_seek(s, windex);
1077 return 0;
1078 }
1079
1080 case SINK_INPUT_MESSAGE_POST_DATA: {
1081 int64_t windex;
1082
1083 pa_assert(chunk);
1084
1085 /* pa_log("sink input post: %lu", (unsigned long) chunk->length); */
1086
1087 windex = pa_memblockq_get_write_index(s->memblockq);
1088
1089 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
1090 pa_log_warn("Failed to push data into queue");
1091 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
1092 pa_memblockq_seek(s->memblockq, chunk->length, PA_SEEK_RELATIVE);
1093 }
1094
1095 handle_seek(s, windex);
1096
1097 return 0;
1098 }
1099
1100 case SINK_INPUT_MESSAGE_DRAIN:
1101 case SINK_INPUT_MESSAGE_FLUSH:
1102 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1103 case SINK_INPUT_MESSAGE_TRIGGER: {
1104
1105 int64_t windex;
1106 pa_sink_input *isync;
1107 void (*func)(pa_memblockq *bq);
1108
1109 switch (code) {
1110 case SINK_INPUT_MESSAGE_FLUSH:
1111 func = pa_memblockq_flush;
1112 break;
1113
1114 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1115 func = pa_memblockq_prebuf_force;
1116 break;
1117
1118 case SINK_INPUT_MESSAGE_DRAIN:
1119 case SINK_INPUT_MESSAGE_TRIGGER:
1120 func = pa_memblockq_prebuf_disable;
1121 break;
1122
1123 default:
1124 pa_assert_not_reached();
1125 }
1126
1127 windex = pa_memblockq_get_write_index(s->memblockq);
1128 func(s->memblockq);
1129 handle_seek(s, windex);
1130
1131 /* Do the same for all other members in the sync group */
1132 for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
1133 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1134 windex = pa_memblockq_get_write_index(ssync->memblockq);
1135 func(ssync->memblockq);
1136 handle_seek(ssync, windex);
1137 }
1138
1139 for (isync = i->sync_next; isync; isync = isync->sync_next) {
1140 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1141 windex = pa_memblockq_get_write_index(ssync->memblockq);
1142 func(ssync->memblockq);
1143 handle_seek(ssync, windex);
1144 }
1145
1146 if (code == SINK_INPUT_MESSAGE_DRAIN) {
1147 if (!pa_memblockq_is_readable(s->memblockq))
1148 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
1149 else {
1150 s->drain_tag = PA_PTR_TO_UINT(userdata);
1151 s->drain_request = TRUE;
1152 }
1153 }
1154
1155 return 0;
1156 }
1157
1158 case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
1159
1160 s->read_index = pa_memblockq_get_read_index(s->memblockq);
1161 s->write_index = pa_memblockq_get_write_index(s->memblockq);
1162 s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
1163 return 0;
1164
1165 case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1166 int64_t windex;
1167
1168 windex = pa_memblockq_get_write_index(s->memblockq);
1169
1170 pa_memblockq_prebuf_force(s->memblockq);
1171
1172 handle_seek(s, windex);
1173
1174 /* Fall through to the default handler */
1175 break;
1176 }
1177
1178 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1179 pa_usec_t *r = userdata;
1180
1181 *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
1182
1183 /* Fall through, the default handler will add in the extra
1184 * latency added by the resampler */
1185 break;
1186 }
1187 }
1188
1189 return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1190 }
1191
1192 /* Called from thread context */
1193 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
1194 playback_stream *s;
1195
1196 pa_sink_input_assert_ref(i);
1197 s = PLAYBACK_STREAM(i->userdata);
1198 playback_stream_assert_ref(s);
1199 pa_assert(chunk);
1200
1201 if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
1202
1203 /* pa_log("UNDERRUN"); */
1204
1205 if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
1206 s->drain_request = FALSE;
1207 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);
1208 } else if (s->underrun == 0)
1209 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
1210
1211 if (s->underrun != (size_t) -1)
1212 s->underrun += nbytes;
1213
1214 /* pa_log("added %llu bytes, total is %llu", (unsigned long long) nbytes, (unsigned long long) s->underrun); */
1215
1216 request_bytes(s);
1217
1218 return -1;
1219 }
1220
1221 /* pa_log("NOTUNDERRUN"); */
1222
1223 s->underrun = 0;
1224
1225 pa_memblockq_drop(s->memblockq, chunk->length);
1226 request_bytes(s);
1227
1228 return 0;
1229 }
1230
1231 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1232 playback_stream *s;
1233
1234 pa_sink_input_assert_ref(i);
1235 s = PLAYBACK_STREAM(i->userdata);
1236 playback_stream_assert_ref(s);
1237
1238 /* If we are in an underrun, then we don't rewind */
1239 if (s->underrun != 0)
1240 return;
1241
1242 pa_memblockq_rewind(s->memblockq, nbytes);
1243 }
1244
1245 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1246 playback_stream *s;
1247
1248 pa_sink_input_assert_ref(i);
1249 s = PLAYBACK_STREAM(i->userdata);
1250 playback_stream_assert_ref(s);
1251
1252 pa_memblockq_set_maxrewind(s->memblockq, nbytes);
1253 }
1254
1255 /* Called from main context */
1256 static void sink_input_kill_cb(pa_sink_input *i) {
1257 playback_stream *s;
1258
1259 pa_sink_input_assert_ref(i);
1260 s = PLAYBACK_STREAM(i->userdata);
1261 playback_stream_assert_ref(s);
1262
1263 send_playback_stream_killed(s);
1264 playback_stream_unlink(s);
1265 }
1266
1267 /* Called from main context */
1268 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
1269 playback_stream *s;
1270 pa_tagstruct *t;
1271
1272 pa_sink_input_assert_ref(i);
1273 s = PLAYBACK_STREAM(i->userdata);
1274 playback_stream_assert_ref(s);
1275
1276 if (s->connection->version < 12)
1277 return;
1278
1279 t = pa_tagstruct_new(NULL, 0);
1280 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED);
1281 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1282 pa_tagstruct_putu32(t, s->index);
1283 pa_tagstruct_put_boolean(t, suspend);
1284 pa_pstream_send_tagstruct(s->connection->pstream, t);
1285 }
1286
1287 /* Called from main context */
1288 static void sink_input_moved_cb(pa_sink_input *i) {
1289 playback_stream *s;
1290 pa_tagstruct *t;
1291
1292 pa_sink_input_assert_ref(i);
1293 s = PLAYBACK_STREAM(i->userdata);
1294 playback_stream_assert_ref(s);
1295
1296 if (s->connection->version < 12)
1297 return;
1298
1299 t = pa_tagstruct_new(NULL, 0);
1300 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED);
1301 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1302 pa_tagstruct_putu32(t, s->index);
1303 pa_tagstruct_putu32(t, i->sink->index);
1304 pa_tagstruct_puts(t, i->sink->name);
1305 pa_tagstruct_put_boolean(t, pa_sink_get_state(i->sink) == PA_SINK_SUSPENDED);
1306 pa_pstream_send_tagstruct(s->connection->pstream, t);
1307 }
1308
1309 /*** source_output callbacks ***/
1310
1311 /* Called from thread context */
1312 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1313 record_stream *s;
1314
1315 pa_source_output_assert_ref(o);
1316 s = RECORD_STREAM(o->userdata);
1317 record_stream_assert_ref(s);
1318 pa_assert(chunk);
1319
1320 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1321 }
1322
1323 static void source_output_kill_cb(pa_source_output *o) {
1324 record_stream *s;
1325
1326 pa_source_output_assert_ref(o);
1327 s = RECORD_STREAM(o->userdata);
1328 record_stream_assert_ref(s);
1329
1330 send_record_stream_killed(s);
1331 record_stream_unlink(s);
1332 }
1333
1334 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1335 record_stream *s;
1336
1337 pa_source_output_assert_ref(o);
1338 s = RECORD_STREAM(o->userdata);
1339 record_stream_assert_ref(s);
1340
1341 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1342
1343 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
1344 }
1345
1346 /* Called from main context */
1347 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
1348 record_stream *s;
1349 pa_tagstruct *t;
1350
1351 pa_source_output_assert_ref(o);
1352 s = RECORD_STREAM(o->userdata);
1353 record_stream_assert_ref(s);
1354
1355 if (s->connection->version < 12)
1356 return;
1357
1358 t = pa_tagstruct_new(NULL, 0);
1359 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED);
1360 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1361 pa_tagstruct_putu32(t, s->index);
1362 pa_tagstruct_put_boolean(t, suspend);
1363 pa_pstream_send_tagstruct(s->connection->pstream, t);
1364 }
1365
1366 /* Called from main context */
1367 static void source_output_moved_cb(pa_source_output *o) {
1368 record_stream *s;
1369 pa_tagstruct *t;
1370
1371 pa_source_output_assert_ref(o);
1372 s = RECORD_STREAM(o->userdata);
1373 record_stream_assert_ref(s);
1374
1375 if (s->connection->version < 12)
1376 return;
1377
1378 t = pa_tagstruct_new(NULL, 0);
1379 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED);
1380 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1381 pa_tagstruct_putu32(t, s->index);
1382 pa_tagstruct_putu32(t, o->source->index);
1383 pa_tagstruct_puts(t, o->source->name);
1384 pa_tagstruct_put_boolean(t, pa_source_get_state(o->source) == PA_SOURCE_SUSPENDED);
1385 pa_pstream_send_tagstruct(s->connection->pstream, t);
1386 }
1387
1388 /*** pdispatch callbacks ***/
1389
1390 static void protocol_error(connection *c) {
1391 pa_log("protocol error, kicking client");
1392 connection_unlink(c);
1393 }
1394
1395 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1396 if (!(expression)) { \
1397 pa_pstream_send_error((pstream), (tag), (error)); \
1398 return; \
1399 } \
1400 } while(0);
1401
1402 static pa_tagstruct *reply_new(uint32_t tag) {
1403 pa_tagstruct *reply;
1404
1405 reply = pa_tagstruct_new(NULL, 0);
1406 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1407 pa_tagstruct_putu32(reply, tag);
1408 return reply;
1409 }
1410
1411 static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1412 connection *c = CONNECTION(userdata);
1413 playback_stream *s;
1414 uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid, missing;
1415 const char *name = NULL, *sink_name;
1416 pa_sample_spec ss;
1417 pa_channel_map map;
1418 pa_tagstruct *reply;
1419 pa_sink *sink = NULL;
1420 pa_cvolume volume;
1421 pa_bool_t
1422 corked = FALSE,
1423 no_remap = FALSE,
1424 no_remix = FALSE,
1425 fix_format = FALSE,
1426 fix_rate = FALSE,
1427 fix_channels = FALSE,
1428 no_move = FALSE,
1429 variable_rate = FALSE,
1430 muted = FALSE,
1431 adjust_latency = FALSE;
1432
1433 pa_sink_input_flags_t flags = 0;
1434 pa_proplist *p;
1435
1436 connection_assert_ref(c);
1437 pa_assert(t);
1438
1439 if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
1440 pa_tagstruct_get(
1441 t,
1442 PA_TAG_SAMPLE_SPEC, &ss,
1443 PA_TAG_CHANNEL_MAP, &map,
1444 PA_TAG_U32, &sink_index,
1445 PA_TAG_STRING, &sink_name,
1446 PA_TAG_U32, &maxlength,
1447 PA_TAG_BOOLEAN, &corked,
1448 PA_TAG_U32, &tlength,
1449 PA_TAG_U32, &prebuf,
1450 PA_TAG_U32, &minreq,
1451 PA_TAG_U32, &syncid,
1452 PA_TAG_CVOLUME, &volume,
1453 PA_TAG_INVALID) < 0) {
1454
1455 protocol_error(c);
1456 return;
1457 }
1458
1459 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1460 CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(sink_name)), tag, PA_ERR_INVALID);
1461 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1462 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1463 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
1464 CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
1465
1466 p = pa_proplist_new();
1467
1468 if (name)
1469 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
1470
1471 if (c->version >= 12) {
1472 /* Since 0.9.8 the user can ask for a couple of additional flags */
1473
1474 if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
1475 pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
1476 pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
1477 pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
1478 pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
1479 pa_tagstruct_get_boolean(t, &no_move) < 0 ||
1480 pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
1481
1482 protocol_error(c);
1483 pa_proplist_free(p);
1484 return;
1485 }
1486 }
1487
1488 if (c->version >= 13) {
1489
1490 if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
1491 pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
1492 pa_tagstruct_get_proplist(t, p) < 0) {
1493 protocol_error(c);
1494 pa_proplist_free(p);
1495 return;
1496 }
1497 }
1498
1499 if (!pa_tagstruct_eof(t)) {
1500 protocol_error(c);
1501 pa_proplist_free(p);
1502 return;
1503 }
1504
1505 if (sink_index != PA_INVALID_INDEX) {
1506
1507 if (!(sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index))) {
1508 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1509 pa_proplist_free(p);
1510 return;
1511 }
1512
1513 } else if (sink_name) {
1514
1515 if (!(sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1))) {
1516 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1517 pa_proplist_free(p);
1518 return;
1519 }
1520 }
1521
1522 flags =
1523 (corked ? PA_SINK_INPUT_START_CORKED : 0) |
1524 (no_remap ? PA_SINK_INPUT_NO_REMAP : 0) |
1525 (no_remix ? PA_SINK_INPUT_NO_REMIX : 0) |
1526 (fix_format ? PA_SINK_INPUT_FIX_FORMAT : 0) |
1527 (fix_rate ? PA_SINK_INPUT_FIX_RATE : 0) |
1528 (fix_channels ? PA_SINK_INPUT_FIX_CHANNELS : 0) |
1529 (no_move ? PA_SINK_INPUT_DONT_MOVE : 0) |
1530 (variable_rate ? PA_SINK_INPUT_VARIABLE_RATE : 0);
1531
1532 s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, &volume, muted, syncid, &missing, flags, p, adjust_latency);
1533 pa_proplist_free(p);
1534
1535 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
1536
1537 reply = reply_new(tag);
1538 pa_tagstruct_putu32(reply, s->index);
1539 pa_assert(s->sink_input);
1540 pa_tagstruct_putu32(reply, s->sink_input->index);
1541 pa_tagstruct_putu32(reply, missing);
1542
1543 /* pa_log("initial request is %u", missing); */
1544
1545 if (c->version >= 9) {
1546 /* Since 0.9.0 we support sending the buffer metrics back to the client */
1547
1548 pa_tagstruct_putu32(reply, (uint32_t) maxlength);
1549 pa_tagstruct_putu32(reply, (uint32_t) tlength);
1550 pa_tagstruct_putu32(reply, (uint32_t) prebuf);
1551 pa_tagstruct_putu32(reply, (uint32_t) minreq);
1552 }
1553
1554 if (c->version >= 12) {
1555 /* Since 0.9.8 we support sending the chosen sample
1556 * spec/channel map/device/suspend status back to the
1557 * client */
1558
1559 pa_tagstruct_put_sample_spec(reply, &ss);
1560 pa_tagstruct_put_channel_map(reply, &map);
1561
1562 pa_tagstruct_putu32(reply, s->sink_input->sink->index);
1563 pa_tagstruct_puts(reply, s->sink_input->sink->name);
1564
1565 pa_tagstruct_put_boolean(reply, pa_sink_get_state(s->sink_input->sink) == PA_SINK_SUSPENDED);
1566 }
1567
1568 if (c->version >= 13)
1569 pa_tagstruct_put_usec(reply, s->sink_latency);
1570
1571 pa_pstream_send_tagstruct(c->pstream, reply);
1572 }
1573
1574 static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1575 connection *c = CONNECTION(userdata);
1576 uint32_t channel;
1577
1578 connection_assert_ref(c);
1579 pa_assert(t);
1580
1581 if (pa_tagstruct_getu32(t, &channel) < 0 ||
1582 !pa_tagstruct_eof(t)) {
1583 protocol_error(c);
1584 return;
1585 }
1586
1587 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1588
1589 switch (command) {
1590
1591 case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
1592 playback_stream *s;
1593 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
1594 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
1595 return;
1596 }
1597
1598 playback_stream_unlink(s);
1599 break;
1600 }
1601
1602 case PA_COMMAND_DELETE_RECORD_STREAM: {
1603 record_stream *s;
1604 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
1605 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
1606 return;
1607 }
1608
1609 record_stream_unlink(s);
1610 break;
1611 }
1612
1613 case PA_COMMAND_DELETE_UPLOAD_STREAM: {
1614 upload_stream *s;
1615
1616 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
1617 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
1618 return;
1619 }
1620
1621 upload_stream_unlink(s);
1622 break;
1623 }
1624
1625 default:
1626 pa_assert_not_reached();
1627 }
1628
1629 pa_pstream_send_simple_ack(c->pstream, tag);
1630 }
1631
1632 static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1633 connection *c = CONNECTION(userdata);
1634 record_stream *s;
1635 uint32_t maxlength, fragment_size;
1636 uint32_t source_index;
1637 const char *name, *source_name;
1638 pa_sample_spec ss;
1639 pa_channel_map map;
1640 pa_tagstruct *reply;
1641 pa_source *source = NULL;
1642 pa_bool_t
1643 corked = FALSE,
1644 no_remap = FALSE,
1645 no_remix = FALSE,
1646 fix_format = FALSE,
1647 fix_rate = FALSE,
1648 fix_channels = FALSE,
1649 no_move = FALSE,
1650 variable_rate = FALSE,
1651 adjust_latency = FALSE;
1652 pa_source_output_flags_t flags = 0;
1653 pa_proplist *p;
1654
1655 connection_assert_ref(c);
1656 pa_assert(t);
1657
1658 if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
1659 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
1660 pa_tagstruct_get_channel_map(t, &map) < 0 ||
1661 pa_tagstruct_getu32(t, &source_index) < 0 ||
1662 pa_tagstruct_gets(t, &source_name) < 0 ||
1663 pa_tagstruct_getu32(t, &maxlength) < 0 ||
1664 pa_tagstruct_get_boolean(t, &corked) < 0 ||
1665 pa_tagstruct_getu32(t, &fragment_size) < 0) {
1666 protocol_error(c);
1667 return;
1668 }
1669
1670 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1671 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1672 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1673 CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID);
1674 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
1675
1676 p = pa_proplist_new();
1677
1678 if (name)
1679 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
1680
1681 if (c->version >= 12) {
1682 /* Since 0.9.8 the user can ask for a couple of additional flags */
1683
1684 if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
1685 pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
1686 pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
1687 pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
1688 pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
1689 pa_tagstruct_get_boolean(t, &no_move) < 0 ||
1690 pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
1691
1692 protocol_error(c);
1693 pa_proplist_free(p);
1694 return;
1695 }
1696 }
1697
1698 if (c->version >= 13) {
1699
1700 if (pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
1701 pa_tagstruct_get_proplist(t, p) < 0) {
1702 protocol_error(c);
1703 pa_proplist_free(p);
1704 return;
1705 }
1706 }
1707
1708 if (!pa_tagstruct_eof(t)) {
1709 protocol_error(c);
1710 pa_proplist_free(p);
1711 return;
1712 }
1713
1714 if (source_index != PA_INVALID_INDEX) {
1715
1716 if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
1717 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1718 pa_proplist_free(p);
1719 return;
1720 }
1721
1722 } else if (source_name) {
1723
1724 if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1))) {
1725 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1726 pa_proplist_free(p);
1727 return;
1728 }
1729 }
1730
1731 flags =
1732 (corked ? PA_SOURCE_OUTPUT_START_CORKED : 0) |
1733 (no_remap ? PA_SOURCE_OUTPUT_NO_REMAP : 0) |
1734 (no_remix ? PA_SOURCE_OUTPUT_NO_REMIX : 0) |
1735 (fix_format ? PA_SOURCE_OUTPUT_FIX_FORMAT : 0) |
1736 (fix_rate ? PA_SOURCE_OUTPUT_FIX_RATE : 0) |
1737 (fix_channels ? PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
1738 (no_move ? PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
1739 (variable_rate ? PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
1740
1741 s = record_stream_new(c, source, &ss, &map, &maxlength, &fragment_size, flags, p, adjust_latency);
1742 pa_proplist_free(p);
1743
1744 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
1745
1746 reply = reply_new(tag);
1747 pa_tagstruct_putu32(reply, s->index);
1748 pa_assert(s->source_output);
1749 pa_tagstruct_putu32(reply, s->source_output->index);
1750
1751 if (c->version >= 9) {
1752 /* Since 0.9 we support sending the buffer metrics back to the client */
1753
1754 pa_tagstruct_putu32(reply, (uint32_t) maxlength);
1755 pa_tagstruct_putu32(reply, (uint32_t) fragment_size);
1756 }
1757
1758 if (c->version >= 12) {
1759 /* Since 0.9.8 we support sending the chosen sample
1760 * spec/channel map/device/suspend status back to the
1761 * client */
1762
1763 pa_tagstruct_put_sample_spec(reply, &ss);
1764 pa_tagstruct_put_channel_map(reply, &map);
1765
1766 pa_tagstruct_putu32(reply, s->source_output->source->index);
1767 pa_tagstruct_puts(reply, s->source_output->source->name);
1768
1769 pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED);
1770 }
1771
1772 if (c->version >= 13)
1773 pa_tagstruct_put_usec(reply, s->source_latency);
1774
1775 pa_pstream_send_tagstruct(c->pstream, reply);
1776 }
1777
1778 static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1779 connection *c = CONNECTION(userdata);
1780
1781 connection_assert_ref(c);
1782 pa_assert(t);
1783
1784 if (!pa_tagstruct_eof(t)) {
1785 protocol_error(c);
1786 return;
1787 }
1788
1789 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1790
1791 c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0);
1792 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
1793 }
1794
1795 static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1796 connection *c = CONNECTION(userdata);
1797 const void*cookie;
1798 pa_tagstruct *reply;
1799 char tmp[16];
1800
1801 connection_assert_ref(c);
1802 pa_assert(t);
1803
1804 if (pa_tagstruct_getu32(t, &c->version) < 0 ||
1805 pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
1806 !pa_tagstruct_eof(t)) {
1807 protocol_error(c);
1808 return;
1809 }
1810
1811 /* Minimum supported version */
1812 if (c->version < 8) {
1813 pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
1814 return;
1815 }
1816
1817 pa_snprintf(tmp, sizeof(tmp), "%u", c->version);
1818 pa_proplist_sets(c->client->proplist, "native-protocol.version", tmp);
1819
1820 if (!c->authorized) {
1821 int success = 0;
1822
1823 #ifdef HAVE_CREDS
1824 const pa_creds *creds;
1825
1826 if ((creds = pa_pdispatch_creds(pd))) {
1827 if (creds->uid == getuid())
1828 success = 1;
1829 else if (c->protocol->auth_group) {
1830 int r;
1831 gid_t gid;
1832
1833 if ((gid = pa_get_gid_of_group(c->protocol->auth_group)) == (gid_t) -1)
1834 pa_log_warn("failed to get GID of group '%s'", c->protocol->auth_group);
1835 else if (gid == creds->gid)
1836 success = 1;
1837 if (!success) {
1838 if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0)
1839 pa_log_warn("failed to check group membership.");
1840 else if (r > 0)
1841 success = 1;
1842 }
1843 }
1844
1845 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
1846 (unsigned long) creds->uid,
1847 (unsigned long) creds->gid,
1848 success);
1849
1850 if (c->version >= 10 &&
1851 pa_mempool_is_shared(c->protocol->core->mempool) &&
1852 creds->uid == getuid()) {
1853
1854 pa_pstream_enable_shm(c->pstream, TRUE);
1855 pa_log_info("Enabled SHM for new connection");
1856 }
1857
1858 }
1859 #endif
1860
1861 if (!success && memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
1862 success = 1;
1863
1864 if (!success) {
1865 pa_log_warn("Denied access to client with invalid authorization data.");
1866 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
1867 return;
1868 }
1869
1870 c->authorized = TRUE;
1871 if (c->auth_timeout_event) {
1872 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
1873 c->auth_timeout_event = NULL;
1874 }
1875 }
1876
1877 reply = reply_new(tag);
1878 pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION);
1879
1880 #ifdef HAVE_CREDS
1881 {
1882 /* SHM support is only enabled after both sides made sure they are the same user. */
1883
1884 pa_creds ucred;
1885
1886 ucred.uid = getuid();
1887 ucred.gid = getgid();
1888
1889 pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
1890 }
1891 #else
1892 pa_pstream_send_tagstruct(c->pstream, reply);
1893 #endif
1894 }
1895
1896 static void command_set_client_name(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1897 connection *c = CONNECTION(userdata);
1898 const char *name = NULL;
1899 pa_proplist *p;
1900 pa_tagstruct *reply;
1901
1902 connection_assert_ref(c);
1903 pa_assert(t);
1904
1905 p = pa_proplist_new();
1906
1907 if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
1908 (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
1909 !pa_tagstruct_eof(t)) {
1910
1911 protocol_error(c);
1912 pa_proplist_free(p);
1913 return;
1914 }
1915
1916 if (name)
1917 if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
1918 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
1919 pa_proplist_free(p);
1920 return;
1921 }
1922
1923 pa_proplist_update(c->client->proplist, PA_UPDATE_REPLACE, p);
1924 pa_proplist_free(p);
1925
1926 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
1927
1928 reply = reply_new(tag);
1929
1930 if (c->version >= 13)
1931 pa_tagstruct_putu32(reply, c->client->index);
1932
1933 pa_pstream_send_tagstruct(c->pstream, reply);
1934 }
1935
1936 static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1937 connection *c = CONNECTION(userdata);
1938 const char *name;
1939 uint32_t idx = PA_IDXSET_INVALID;
1940
1941 connection_assert_ref(c);
1942 pa_assert(t);
1943
1944 if (pa_tagstruct_gets(t, &name) < 0 ||
1945 !pa_tagstruct_eof(t)) {
1946 protocol_error(c);
1947 return;
1948 }
1949
1950 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1951 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1952
1953 if (command == PA_COMMAND_LOOKUP_SINK) {
1954 pa_sink *sink;
1955 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1)))
1956 idx = sink->index;
1957 } else {
1958 pa_source *source;
1959 pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
1960 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1)))
1961 idx = source->index;
1962 }
1963
1964 if (idx == PA_IDXSET_INVALID)
1965 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1966 else {
1967 pa_tagstruct *reply;
1968 reply = reply_new(tag);
1969 pa_tagstruct_putu32(reply, idx);
1970 pa_pstream_send_tagstruct(c->pstream, reply);
1971 }
1972 }
1973
1974 static void command_drain_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1975 connection *c = CONNECTION(userdata);
1976 uint32_t idx;
1977 playback_stream *s;
1978
1979 connection_assert_ref(c);
1980 pa_assert(t);
1981
1982 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1983 !pa_tagstruct_eof(t)) {
1984 protocol_error(c);
1985 return;
1986 }
1987
1988 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1989 s = pa_idxset_get_by_index(c->output_streams, idx);
1990 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1991 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
1992
1993 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);
1994 }
1995
1996 static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1997 connection *c = CONNECTION(userdata);
1998 pa_tagstruct *reply;
1999 const pa_mempool_stat *stat;
2000
2001 connection_assert_ref(c);
2002 pa_assert(t);
2003
2004 if (!pa_tagstruct_eof(t)) {
2005 protocol_error(c);
2006 return;
2007 }
2008
2009 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2010
2011 stat = pa_mempool_get_stat(c->protocol->core->mempool);
2012
2013 reply = reply_new(tag);
2014 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
2015 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
2016 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
2017 pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
2018 pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core));
2019 pa_pstream_send_tagstruct(c->pstream, reply);
2020 }
2021
2022 static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2023 connection *c = CONNECTION(userdata);
2024 pa_tagstruct *reply;
2025 playback_stream *s;
2026 struct timeval tv, now;
2027 uint32_t idx;
2028 pa_usec_t latency;
2029
2030 connection_assert_ref(c);
2031 pa_assert(t);
2032
2033 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2034 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2035 !pa_tagstruct_eof(t)) {
2036 protocol_error(c);
2037 return;
2038 }
2039
2040 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2041 s = pa_idxset_get_by_index(c->output_streams, idx);
2042 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2043 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2044 CHECK_VALIDITY(c->pstream, pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_LATENCY, s, 0, NULL) == 0, tag, PA_ERR_NOENTITY)
2045
2046 reply = reply_new(tag);
2047
2048 latency = pa_sink_get_latency(s->sink_input->sink);
2049 latency += pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sample_spec);
2050
2051 pa_tagstruct_put_usec(reply, latency);
2052
2053 pa_tagstruct_put_usec(reply, 0);
2054 pa_tagstruct_put_boolean(reply, pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
2055 pa_tagstruct_put_timeval(reply, &tv);
2056 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2057 pa_tagstruct_puts64(reply, s->write_index);
2058 pa_tagstruct_puts64(reply, s->read_index);
2059 pa_pstream_send_tagstruct(c->pstream, reply);
2060 }
2061
2062 static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2063 connection *c = CONNECTION(userdata);
2064 pa_tagstruct *reply;
2065 record_stream *s;
2066 struct timeval tv, now;
2067 uint32_t idx;
2068
2069 connection_assert_ref(c);
2070 pa_assert(t);
2071
2072 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2073 pa_tagstruct_get_timeval(t, &tv) < 0 ||
2074 !pa_tagstruct_eof(t)) {
2075 protocol_error(c);
2076 return;
2077 }
2078
2079 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2080 s = pa_idxset_get_by_index(c->record_streams, idx);
2081 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2082
2083 reply = reply_new(tag);
2084 pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
2085 pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
2086 pa_tagstruct_put_boolean(reply, FALSE);
2087 pa_tagstruct_put_timeval(reply, &tv);
2088 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2089 pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
2090 pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
2091 pa_pstream_send_tagstruct(c->pstream, reply);
2092 }
2093
2094 static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2095 connection *c = CONNECTION(userdata);
2096 upload_stream *s;
2097 uint32_t length;
2098 const char *name = NULL;
2099 pa_sample_spec ss;
2100 pa_channel_map map;
2101 pa_tagstruct *reply;
2102 pa_proplist *p;
2103
2104 connection_assert_ref(c);
2105 pa_assert(t);
2106
2107 if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
2108 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2109 pa_tagstruct_get_channel_map(t, &map) < 0 ||
2110 pa_tagstruct_getu32(t, &length) < 0) {
2111 protocol_error(c);
2112 return;
2113 }
2114
2115 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2116 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2117 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2118 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2119 CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
2120 CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
2121
2122 if (c->version < 13)
2123 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
2124
2125 p = pa_proplist_new();
2126
2127 if (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) {
2128 protocol_error(c);
2129 pa_proplist_free(p);
2130 return;
2131 }
2132
2133 if (c->version < 13)
2134 pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2135
2136 s = upload_stream_new(c, &ss, &map, name, length, p);
2137 pa_proplist_free(p);
2138
2139 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
2140
2141 reply = reply_new(tag);
2142 pa_tagstruct_putu32(reply, s->index);
2143 pa_tagstruct_putu32(reply, length);
2144 pa_pstream_send_tagstruct(c->pstream, reply);
2145 }
2146
2147 static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2148 connection *c = CONNECTION(userdata);
2149 uint32_t channel;
2150 upload_stream *s;
2151 uint32_t idx;
2152
2153 connection_assert_ref(c);
2154 pa_assert(t);
2155
2156 if (pa_tagstruct_getu32(t, &channel) < 0 ||
2157 !pa_tagstruct_eof(t)) {
2158 protocol_error(c);
2159 return;
2160 }
2161
2162 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2163
2164 s = pa_idxset_get_by_index(c->output_streams, channel);
2165 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2166 CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2167
2168 if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
2169 pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
2170 else
2171 pa_pstream_send_simple_ack(c->pstream, tag);
2172
2173 upload_stream_unlink(s);
2174 }
2175
2176 static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2177 connection *c = CONNECTION(userdata);
2178 uint32_t sink_index;
2179 pa_volume_t volume;
2180 pa_sink *sink;
2181 const char *name, *sink_name;
2182 uint32_t idx;
2183 pa_proplist *p;
2184 pa_tagstruct *reply;
2185
2186 connection_assert_ref(c);
2187 pa_assert(t);
2188
2189 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2190
2191 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
2192 pa_tagstruct_gets(t, &sink_name) < 0 ||
2193 pa_tagstruct_getu32(t, &volume) < 0 ||
2194 pa_tagstruct_gets(t, &name) < 0) {
2195 protocol_error(c);
2196 return;
2197 }
2198
2199 CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2200 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
2201
2202 if (sink_index != PA_INVALID_INDEX)
2203 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
2204 else
2205 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
2206
2207 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
2208
2209 p = pa_proplist_new();
2210
2211 if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2212 !pa_tagstruct_eof(t)) {
2213 protocol_error(c);
2214 pa_proplist_free(p);
2215 return;
2216 }
2217
2218 if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
2219 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2220 pa_proplist_free(p);
2221 return;
2222 }
2223
2224 pa_proplist_free(p);
2225
2226 reply = reply_new(tag);
2227
2228 if (c->version >= 13)
2229 pa_tagstruct_putu32(reply, idx);
2230
2231 pa_pstream_send_tagstruct(c->pstream, reply);
2232 }
2233
2234 static void command_remove_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2235 connection *c = CONNECTION(userdata);
2236 const char *name;
2237
2238 connection_assert_ref(c);
2239 pa_assert(t);
2240
2241 if (pa_tagstruct_gets(t, &name) < 0 ||
2242 !pa_tagstruct_eof(t)) {
2243 protocol_error(c);
2244 return;
2245 }
2246
2247 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2248 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
2249
2250 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
2251 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2252 return;
2253 }
2254
2255 pa_pstream_send_simple_ack(c->pstream, tag);
2256 }
2257
2258 static void fixup_sample_spec(connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
2259 pa_assert(c);
2260 pa_assert(fixed);
2261 pa_assert(original);
2262
2263 *fixed = *original;
2264
2265 if (c->version < 12) {
2266 /* Before protocol version 12 we didn't support S32 samples,
2267 * so we need to lie about this to the client */
2268
2269 if (fixed->format == PA_SAMPLE_S32LE)
2270 fixed->format = PA_SAMPLE_FLOAT32LE;
2271 if (fixed->format == PA_SAMPLE_S32BE)
2272 fixed->format = PA_SAMPLE_FLOAT32BE;
2273 }
2274 }
2275
2276 static void sink_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink *sink) {
2277 pa_sample_spec fixed_ss;
2278
2279 pa_assert(t);
2280 pa_sink_assert_ref(sink);
2281
2282 fixup_sample_spec(c, &fixed_ss, &sink->sample_spec);
2283
2284 pa_tagstruct_put(
2285 t,
2286 PA_TAG_U32, sink->index,
2287 PA_TAG_STRING, sink->name,
2288 PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2289 PA_TAG_SAMPLE_SPEC, &fixed_ss,
2290 PA_TAG_CHANNEL_MAP, &sink->channel_map,
2291 PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
2292 PA_TAG_CVOLUME, pa_sink_get_volume(sink),
2293 PA_TAG_BOOLEAN, pa_sink_get_mute(sink),
2294 PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
2295 PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
2296 PA_TAG_USEC, pa_sink_get_latency(sink),
2297 PA_TAG_STRING, sink->driver,
2298 PA_TAG_U32, sink->flags,
2299 PA_TAG_INVALID);
2300
2301 if (c->version >= 13) {
2302 pa_tagstruct_put_proplist(t, sink->proplist);
2303 pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
2304 }
2305 }
2306
2307 static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *source) {
2308 pa_sample_spec fixed_ss;
2309
2310 pa_assert(t);
2311 pa_source_assert_ref(source);
2312
2313 fixup_sample_spec(c, &fixed_ss, &source->sample_spec);
2314
2315 pa_tagstruct_put(
2316 t,
2317 PA_TAG_U32, source->index,
2318 PA_TAG_STRING, source->name,
2319 PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2320 PA_TAG_SAMPLE_SPEC, &fixed_ss,
2321 PA_TAG_CHANNEL_MAP, &source->channel_map,
2322 PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
2323 PA_TAG_CVOLUME, pa_source_get_volume(source),
2324 PA_TAG_BOOLEAN, pa_source_get_mute(source),
2325 PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
2326 PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
2327 PA_TAG_USEC, pa_source_get_latency(source),
2328 PA_TAG_STRING, source->driver,
2329 PA_TAG_U32, source->flags,
2330 PA_TAG_INVALID);
2331
2332 if (c->version >= 13) {
2333 pa_tagstruct_put_proplist(t, source->proplist);
2334 pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
2335 }
2336 }
2337
2338
2339 static void client_fill_tagstruct(connection *c, pa_tagstruct *t, pa_client *client) {
2340 pa_assert(t);
2341 pa_assert(client);
2342
2343 pa_tagstruct_putu32(t, client->index);
2344 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
2345 pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
2346 pa_tagstruct_puts(t, client->driver);
2347
2348 if (c->version >= 13)
2349 pa_tagstruct_put_proplist(t, client->proplist);
2350
2351 }
2352
2353 static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
2354 pa_assert(t);
2355 pa_assert(module);
2356
2357 pa_tagstruct_putu32(t, module->index);
2358 pa_tagstruct_puts(t, module->name);
2359 pa_tagstruct_puts(t, module->argument);
2360 pa_tagstruct_putu32(t, module->n_used);
2361 pa_tagstruct_put_boolean(t, module->auto_unload);
2362 }
2363
2364 static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_input *s) {
2365 pa_sample_spec fixed_ss;
2366
2367 pa_assert(t);
2368 pa_sink_input_assert_ref(s);
2369
2370 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
2371
2372 pa_tagstruct_putu32(t, s->index);
2373 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
2374 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
2375 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
2376 pa_tagstruct_putu32(t, s->sink->index);
2377 pa_tagstruct_put_sample_spec(t, &fixed_ss);
2378 pa_tagstruct_put_channel_map(t, &s->channel_map);
2379 pa_tagstruct_put_cvolume(t, &s->volume);
2380 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
2381 pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
2382 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
2383 pa_tagstruct_puts(t, s->driver);
2384 if (c->version >= 11)
2385 pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
2386 if (c->version >= 13)
2387 pa_tagstruct_put_proplist(t, s->proplist);
2388 }
2389
2390 static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source_output *s) {
2391 pa_sample_spec fixed_ss;
2392
2393 pa_assert(t);
2394 pa_source_output_assert_ref(s);
2395
2396 fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
2397
2398 pa_tagstruct_putu32(t, s->index);
2399 pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
2400 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
2401 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
2402 pa_tagstruct_putu32(t, s->source->index);
2403 pa_tagstruct_put_sample_spec(t, &fixed_ss);
2404 pa_tagstruct_put_channel_map(t, &s->channel_map);
2405 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s));
2406 pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
2407 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
2408 pa_tagstruct_puts(t, s->driver);
2409
2410 if (c->version >= 13)
2411 pa_tagstruct_put_proplist(t, s->proplist);
2412 }
2413
2414 static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entry *e) {
2415 pa_sample_spec fixed_ss;
2416
2417 pa_assert(t);
2418 pa_assert(e);
2419
2420 fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
2421
2422 pa_tagstruct_putu32(t, e->index);
2423 pa_tagstruct_puts(t, e->name);
2424 pa_tagstruct_put_cvolume(t, &e->volume);
2425 pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
2426 pa_tagstruct_put_sample_spec(t, &fixed_ss);
2427 pa_tagstruct_put_channel_map(t, &e->channel_map);
2428 pa_tagstruct_putu32(t, e->memchunk.length);
2429 pa_tagstruct_put_boolean(t, e->lazy);
2430 pa_tagstruct_puts(t, e->filename);
2431
2432 if (c->version >= 13)
2433 pa_tagstruct_put_proplist(t, e->proplist);
2434 }
2435
2436 static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2437 connection *c = CONNECTION(userdata);
2438 uint32_t idx;
2439 pa_sink *sink = NULL;
2440 pa_source *source = NULL;
2441 pa_client *client = NULL;
2442 pa_module *module = NULL;
2443 pa_sink_input *si = NULL;
2444 pa_source_output *so = NULL;
2445 pa_scache_entry *sce = NULL;
2446 const char *name;
2447 pa_tagstruct *reply;
2448
2449 connection_assert_ref(c);
2450 pa_assert(t);
2451
2452 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2453 (command != PA_COMMAND_GET_CLIENT_INFO &&
2454 command != PA_COMMAND_GET_MODULE_INFO &&
2455 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
2456 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
2457 pa_tagstruct_gets(t, &name) < 0) ||
2458 !pa_tagstruct_eof(t)) {
2459 protocol_error(c);
2460 return;
2461 }
2462
2463 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2464 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2465
2466 if (command == PA_COMMAND_GET_SINK_INFO) {
2467 if (idx != PA_INVALID_INDEX)
2468 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
2469 else
2470 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
2471 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
2472 if (idx != PA_INVALID_INDEX)
2473 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
2474 else
2475 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
2476 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
2477 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
2478 else if (command == PA_COMMAND_GET_MODULE_INFO)
2479 module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
2480 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
2481 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
2482 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
2483 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
2484 else {
2485 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
2486 if (idx != PA_INVALID_INDEX)
2487 sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
2488 else
2489 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0);
2490 }
2491
2492 if (!sink && !source && !client && !module && !si && !so && !sce) {
2493 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2494 return;
2495 }
2496
2497 reply = reply_new(tag);
2498 if (sink)
2499 sink_fill_tagstruct(c, reply, sink);
2500 else if (source)
2501 source_fill_tagstruct(c, reply, source);
2502 else if (client)
2503 client_fill_tagstruct(c, reply, client);
2504 else if (module)
2505 module_fill_tagstruct(reply, module);
2506 else if (si)
2507 sink_input_fill_tagstruct(c, reply, si);
2508 else if (so)
2509 source_output_fill_tagstruct(c, reply, so);
2510 else
2511 scache_fill_tagstruct(c, reply, sce);
2512 pa_pstream_send_tagstruct(c->pstream, reply);
2513 }
2514
2515 static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2516 connection *c = CONNECTION(userdata);
2517 pa_idxset *i;
2518 uint32_t idx;
2519 void *p;
2520 pa_tagstruct *reply;
2521
2522 connection_assert_ref(c);
2523 pa_assert(t);
2524
2525 if (!pa_tagstruct_eof(t)) {
2526 protocol_error(c);
2527 return;
2528 }
2529
2530 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2531
2532 reply = reply_new(tag);
2533
2534 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
2535 i = c->protocol->core->sinks;
2536 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
2537 i = c->protocol->core->sources;
2538 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
2539 i = c->protocol->core->clients;
2540 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
2541 i = c->protocol->core->modules;
2542 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
2543 i = c->protocol->core->sink_inputs;
2544 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
2545 i = c->protocol->core->source_outputs;
2546 else {
2547 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
2548 i = c->protocol->core->scache;
2549 }
2550
2551 if (i) {
2552 for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
2553 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
2554 sink_fill_tagstruct(c, reply, p);
2555 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
2556 source_fill_tagstruct(c, reply, p);
2557 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
2558 client_fill_tagstruct(c, reply, p);
2559 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
2560 module_fill_tagstruct(reply, p);
2561 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
2562 sink_input_fill_tagstruct(c, reply, p);
2563 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
2564 source_output_fill_tagstruct(c, reply, p);
2565 else {
2566 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
2567 scache_fill_tagstruct(c, reply, p);
2568 }
2569 }
2570 }
2571
2572 pa_pstream_send_tagstruct(c->pstream, reply);
2573 }
2574
2575 static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2576 connection *c = CONNECTION(userdata);
2577 pa_tagstruct *reply;
2578 char txt[256];
2579 const char *n;
2580 pa_sample_spec fixed_ss;
2581
2582 connection_assert_ref(c);
2583 pa_assert(t);
2584
2585 if (!pa_tagstruct_eof(t)) {
2586 protocol_error(c);
2587 return;
2588 }
2589
2590 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2591
2592 reply = reply_new(tag);
2593 pa_tagstruct_puts(reply, PACKAGE_NAME);
2594 pa_tagstruct_puts(reply, PACKAGE_VERSION);
2595 pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt)));
2596 pa_tagstruct_puts(reply, pa_get_host_name(txt, sizeof(txt)));
2597
2598 fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
2599 pa_tagstruct_put_sample_spec(reply, &fixed_ss);
2600
2601 n = pa_namereg_get_default_sink_name(c->protocol->core);
2602 pa_tagstruct_puts(reply, n);
2603 n = pa_namereg_get_default_source_name(c->protocol->core);
2604 pa_tagstruct_puts(reply, n);
2605
2606 pa_tagstruct_putu32(reply, c->protocol->core->cookie);
2607
2608 pa_pstream_send_tagstruct(c->pstream, reply);
2609 }
2610
2611 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
2612 pa_tagstruct *t;
2613 connection *c = CONNECTION(userdata);
2614
2615 connection_assert_ref(c);
2616
2617 t = pa_tagstruct_new(NULL, 0);
2618 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
2619 pa_tagstruct_putu32(t, (uint32_t) -1);
2620 pa_tagstruct_putu32(t, e);
2621 pa_tagstruct_putu32(t, idx);
2622 pa_pstream_send_tagstruct(c->pstream, t);
2623 }
2624
2625 static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2626 connection *c = CONNECTION(userdata);
2627 pa_subscription_mask_t m;
2628
2629 connection_assert_ref(c);
2630 pa_assert(t);
2631
2632 if (pa_tagstruct_getu32(t, &m) < 0 ||
2633 !pa_tagstruct_eof(t)) {
2634 protocol_error(c);
2635 return;
2636 }
2637
2638 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2639 CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
2640
2641 if (c->subscription)
2642 pa_subscription_free(c->subscription);
2643
2644 if (m != 0) {
2645 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
2646 pa_assert(c->subscription);
2647 } else
2648 c->subscription = NULL;
2649
2650 pa_pstream_send_simple_ack(c->pstream, tag);
2651 }
2652
2653 static void command_set_volume(
2654 PA_GCC_UNUSED pa_pdispatch *pd,
2655 uint32_t command,
2656 uint32_t tag,
2657 pa_tagstruct *t,
2658 void *userdata) {
2659
2660 connection *c = CONNECTION(userdata);
2661 uint32_t idx;
2662 pa_cvolume volume;
2663 pa_sink *sink = NULL;
2664 pa_source *source = NULL;
2665 pa_sink_input *si = NULL;
2666 const char *name = NULL;
2667
2668 connection_assert_ref(c);
2669 pa_assert(t);
2670
2671 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2672 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
2673 (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
2674 pa_tagstruct_get_cvolume(t, &volume) ||
2675 !pa_tagstruct_eof(t)) {
2676 protocol_error(c);
2677 return;
2678 }
2679
2680 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2681 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2682 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
2683
2684 switch (command) {
2685
2686 case PA_COMMAND_SET_SINK_VOLUME:
2687 if (idx != PA_INVALID_INDEX)
2688 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
2689 else
2690 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
2691 break;
2692
2693 case PA_COMMAND_SET_SOURCE_VOLUME:
2694 if (idx != PA_INVALID_INDEX)
2695 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
2696 else
2697 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
2698 break;
2699
2700 case PA_COMMAND_SET_SINK_INPUT_VOLUME:
2701 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
2702 break;
2703
2704 default:
2705 pa_assert_not_reached();
2706 }
2707
2708 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
2709
2710 if (sink)
2711 pa_sink_set_volume(sink, &volume);
2712 else if (source)
2713 pa_source_set_volume(source, &volume);
2714 else if (si)
2715 pa_sink_input_set_volume(si, &volume);
2716
2717 pa_pstream_send_simple_ack(c->pstream, tag);
2718 }
2719
2720 static void command_set_mute(
2721 PA_GCC_UNUSED pa_pdispatch *pd,
2722 uint32_t command,
2723 uint32_t tag,
2724 pa_tagstruct *t,
2725 void *userdata) {
2726
2727 connection *c = CONNECTION(userdata);
2728 uint32_t idx;
2729 pa_bool_t mute;
2730 pa_sink *sink = NULL;
2731 pa_source *source = NULL;
2732 pa_sink_input *si = NULL;
2733 const char *name = NULL;
2734
2735 connection_assert_ref(c);
2736 pa_assert(t);
2737
2738 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2739 (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
2740 (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
2741 pa_tagstruct_get_boolean(t, &mute) ||
2742 !pa_tagstruct_eof(t)) {
2743 protocol_error(c);
2744 return;
2745 }
2746
2747 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2748 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2749
2750 switch (command) {
2751
2752 case PA_COMMAND_SET_SINK_MUTE:
2753
2754 if (idx != PA_INVALID_INDEX)
2755 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
2756 else
2757 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
2758
2759 break;
2760
2761 case PA_COMMAND_SET_SOURCE_MUTE:
2762 if (idx != PA_INVALID_INDEX)
2763 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
2764 else
2765 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
2766
2767 break;
2768
2769 case PA_COMMAND_SET_SINK_INPUT_MUTE:
2770 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
2771 break;
2772
2773 default:
2774 pa_assert_not_reached();
2775 }
2776
2777 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
2778
2779 if (sink)
2780 pa_sink_set_mute(sink, mute);
2781 else if (source)
2782 pa_source_set_mute(source, mute);
2783 else if (si)
2784 pa_sink_input_set_mute(si, mute);
2785
2786 pa_pstream_send_simple_ack(c->pstream, tag);
2787 }
2788
2789 static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2790 connection *c = CONNECTION(userdata);
2791 uint32_t idx;
2792 pa_bool_t b;
2793 playback_stream *s;
2794
2795 connection_assert_ref(c);
2796 pa_assert(t);
2797
2798 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2799 pa_tagstruct_get_boolean(t, &b) < 0 ||
2800 !pa_tagstruct_eof(t)) {
2801 protocol_error(c);
2802 return;
2803 }
2804
2805 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2806 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2807 s = pa_idxset_get_by_index(c->output_streams, idx);
2808 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2809 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2810
2811 pa_sink_input_cork(s->sink_input, b);
2812 pa_pstream_send_simple_ack(c->pstream, tag);
2813 }
2814
2815 static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2816 connection *c = CONNECTION(userdata);
2817 uint32_t idx;
2818 playback_stream *s;
2819
2820 connection_assert_ref(c);
2821 pa_assert(t);
2822
2823 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2824 !pa_tagstruct_eof(t)) {
2825 protocol_error(c);
2826 return;
2827 }
2828
2829 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2830 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2831 s = pa_idxset_get_by_index(c->output_streams, idx);
2832 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2833 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2834
2835 switch (command) {
2836 case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
2837 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
2838 break;
2839
2840 case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
2841 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
2842 break;
2843
2844 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
2845 pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
2846 break;
2847
2848 default:
2849 pa_assert_not_reached();
2850 }
2851
2852 pa_pstream_send_simple_ack(c->pstream, tag);
2853 }
2854
2855 static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2856 connection *c = CONNECTION(userdata);
2857 uint32_t idx;
2858 record_stream *s;
2859 pa_bool_t b;
2860
2861 connection_assert_ref(c);
2862 pa_assert(t);
2863
2864 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2865 pa_tagstruct_get_boolean(t, &b) < 0 ||
2866 !pa_tagstruct_eof(t)) {
2867 protocol_error(c);
2868 return;
2869 }
2870
2871 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2872 s = pa_idxset_get_by_index(c->record_streams, idx);
2873 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2874
2875 pa_source_output_cork(s->source_output, b);
2876 pa_memblockq_prebuf_force(s->memblockq);
2877 pa_pstream_send_simple_ack(c->pstream, tag);
2878 }
2879
2880 static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2881 connection *c = CONNECTION(userdata);
2882 uint32_t idx;
2883 record_stream *s;
2884
2885 connection_assert_ref(c);
2886 pa_assert(t);
2887
2888 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2889 !pa_tagstruct_eof(t)) {
2890 protocol_error(c);
2891 return;
2892 }
2893
2894 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2895 s = pa_idxset_get_by_index(c->record_streams, idx);
2896 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2897
2898 pa_memblockq_flush(s->memblockq);
2899 pa_pstream_send_simple_ack(c->pstream, tag);
2900 }
2901
2902 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2903 connection *c = CONNECTION(userdata);
2904 uint32_t idx;
2905 uint32_t maxlength, tlength, prebuf, minreq, fragsize;
2906 pa_tagstruct *reply;
2907
2908 connection_assert_ref(c);
2909 pa_assert(t);
2910
2911 if (pa_tagstruct_getu32(t, &idx) < 0) {
2912 protocol_error(c);
2913 return;
2914 }
2915
2916 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2917
2918 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
2919 playback_stream *s;
2920
2921 s = pa_idxset_get_by_index(c->output_streams, idx);
2922 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2923 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2924
2925 if (pa_tagstruct_get(
2926 t,
2927 PA_TAG_U32, &maxlength,
2928 PA_TAG_U32, &tlength,
2929 PA_TAG_U32, &prebuf,
2930 PA_TAG_U32, &minreq,
2931 PA_TAG_INVALID) < 0 ||
2932 !pa_tagstruct_eof(t)) {
2933 protocol_error(c);
2934 return;
2935 }
2936
2937 if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
2938 maxlength = MAX_MEMBLOCKQ_LENGTH;
2939 if (tlength <= 0)
2940 tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*1000, &s->sink_input->sample_spec);
2941 if (minreq <= 0)
2942 minreq = (tlength*9)/10;
2943 if (prebuf <= 0)
2944 prebuf = tlength;
2945
2946 pa_memblockq_set_maxlength(s->memblockq, maxlength);
2947 pa_memblockq_set_tlength(s->memblockq, tlength);
2948 pa_memblockq_set_prebuf(s->memblockq, prebuf);
2949 pa_memblockq_set_minreq(s->memblockq, minreq);
2950
2951 reply = reply_new(tag);
2952 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
2953 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_tlength(s->memblockq));
2954 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq));
2955 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq));
2956
2957 } else {
2958 record_stream *s;
2959 size_t base;
2960 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
2961
2962 s = pa_idxset_get_by_index(c->record_streams, idx);
2963 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2964
2965 if (pa_tagstruct_get(
2966 t,
2967 PA_TAG_U32, &maxlength,
2968 PA_TAG_U32, &fragsize,
2969 PA_TAG_INVALID) < 0 ||
2970 !pa_tagstruct_eof(t)) {
2971 protocol_error(c);
2972 return;
2973 }
2974
2975 if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
2976 maxlength = MAX_MEMBLOCKQ_LENGTH;
2977 if (fragsize <= 0)
2978 fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &s->source_output->sample_spec);
2979
2980 pa_memblockq_set_maxlength(s->memblockq, maxlength);
2981
2982 base = pa_frame_size(&s->source_output->sample_spec);
2983 s->fragment_size = (fragsize/base)*base;
2984 if (s->fragment_size <= 0)
2985 s->fragment_size = base;
2986
2987 if (s->fragment_size > pa_memblockq_get_maxlength(s->memblockq))
2988 s->fragment_size = pa_memblockq_get_maxlength(s->memblockq);
2989
2990 reply = reply_new(tag);
2991 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
2992 pa_tagstruct_putu32(reply, s->fragment_size);
2993 }
2994
2995 pa_pstream_send_tagstruct(c->pstream, reply);
2996 }
2997
2998 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2999 connection *c = CONNECTION(userdata);
3000 uint32_t idx;
3001 uint32_t rate;
3002
3003 connection_assert_ref(c);
3004 pa_assert(t);
3005
3006 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3007 pa_tagstruct_getu32(t, &rate) < 0 ||
3008 !pa_tagstruct_eof(t)) {
3009 protocol_error(c);
3010 return;
3011 }
3012
3013 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3014 CHECK_VALIDITY(c->pstream, rate > 0 && rate <= PA_RATE_MAX, tag, PA_ERR_INVALID);
3015
3016 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
3017 playback_stream *s;
3018
3019 s = pa_idxset_get_by_index(c->output_streams, idx);
3020 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3021 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3022
3023 pa_sink_input_set_rate(s->sink_input, rate);
3024
3025 } else {
3026 record_stream *s;
3027 pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
3028
3029 s = pa_idxset_get_by_index(c->record_streams, idx);
3030 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3031
3032 pa_source_output_set_rate(s->source_output, rate);
3033 }
3034
3035 pa_pstream_send_simple_ack(c->pstream, tag);
3036 }
3037
3038 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3039 connection *c = CONNECTION(userdata);
3040 uint32_t idx;
3041 uint32_t mode;
3042 pa_proplist *p;
3043
3044 connection_assert_ref(c);
3045 pa_assert(t);
3046
3047 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3048
3049 p = pa_proplist_new();
3050
3051 if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
3052
3053 if (pa_tagstruct_getu32(t, &mode) < 0 ||
3054 pa_tagstruct_get_proplist(t, p) < 0 ||
3055 !pa_tagstruct_eof(t)) {
3056 protocol_error(c);
3057 pa_proplist_free(p);
3058 return;
3059 }
3060
3061 } else {
3062
3063 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3064 pa_tagstruct_getu32(t, &mode) < 0 ||
3065 pa_tagstruct_get_proplist(t, p) < 0 ||
3066 !pa_tagstruct_eof(t)) {
3067 protocol_error(c);
3068 pa_proplist_free(p);
3069 return;
3070 }
3071 }
3072
3073 CHECK_VALIDITY(c->pstream, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, tag, PA_ERR_INVALID);
3074
3075 if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
3076 playback_stream *s;
3077
3078 s = pa_idxset_get_by_index(c->output_streams, idx);
3079 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3080 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3081
3082 pa_proplist_update(s->sink_input->proplist, mode, p);
3083 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
3084
3085 } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
3086 record_stream *s;
3087
3088 s = pa_idxset_get_by_index(c->record_streams, idx);
3089 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3090
3091 pa_proplist_update(s->source_output->proplist, mode, p);
3092 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
3093 } else {
3094 pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
3095
3096 pa_proplist_update(c->client->proplist, mode, p);
3097 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
3098 }
3099
3100 pa_pstream_send_simple_ack(c->pstream, tag);
3101 }
3102
3103 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3104 connection *c = CONNECTION(userdata);
3105 uint32_t idx;
3106 unsigned changed = 0;
3107 pa_proplist *p;
3108 pa_strlist *l = NULL;
3109
3110 connection_assert_ref(c);
3111 pa_assert(t);
3112
3113 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3114
3115 if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
3116
3117 if (pa_tagstruct_getu32(t, &idx) < 0) {
3118 protocol_error(c);
3119 return;
3120 }
3121 }
3122
3123 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3124 playback_stream *s;
3125
3126 s = pa_idxset_get_by_index(c->output_streams, idx);
3127 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3128 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3129
3130 p = s->sink_input->proplist;
3131
3132 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3133 record_stream *s;
3134
3135 s = pa_idxset_get_by_index(c->record_streams, idx);
3136 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3137
3138 p = s->source_output->proplist;
3139 } else {
3140 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3141
3142 p = c->client->proplist;
3143 }
3144
3145 for (;;) {
3146 const char *k;
3147
3148 if (pa_tagstruct_gets(t, &k) < 0) {
3149 protocol_error(c);
3150 pa_strlist_free(l);
3151 return;
3152 }
3153
3154 if (!k)
3155 break;
3156
3157 l = pa_strlist_prepend(l, k);
3158 }
3159
3160 if (!pa_tagstruct_eof(t)) {
3161 protocol_error(c);
3162 pa_strlist_free(l);
3163 return;
3164 }
3165
3166 for (;;) {
3167 char *z;
3168
3169 l = pa_strlist_pop(l, &z);
3170
3171 if (!z)
3172 break;
3173
3174 changed += pa_proplist_unset(p, z) >= 0;
3175 pa_xfree(z);
3176 }
3177
3178 pa_pstream_send_simple_ack(c->pstream, tag);
3179
3180 if (changed) {
3181 if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3182 playback_stream *s;
3183
3184 s = pa_idxset_get_by_index(c->output_streams, idx);
3185 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
3186
3187 } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3188 record_stream *s;
3189
3190 s = pa_idxset_get_by_index(c->record_streams, idx);
3191 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
3192
3193 } else {
3194 pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3195 pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
3196 }
3197 }
3198 }
3199
3200 static void command_set_default_sink_or_source(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3201 connection *c = CONNECTION(userdata);
3202 const char *s;
3203
3204 connection_assert_ref(c);
3205 pa_assert(t);
3206
3207 if (pa_tagstruct_gets(t, &s) < 0 ||
3208 !pa_tagstruct_eof(t)) {
3209 protocol_error(c);
3210 return;
3211 }
3212
3213 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3214 CHECK_VALIDITY(c->pstream, !s || (*s && pa_utf8_valid(s)), tag, PA_ERR_INVALID);
3215
3216 pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK);
3217 pa_pstream_send_simple_ack(c->pstream, tag);
3218 }
3219
3220 static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3221 connection *c = CONNECTION(userdata);
3222 uint32_t idx;
3223 const char *name;
3224
3225 connection_assert_ref(c);
3226 pa_assert(t);
3227
3228 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3229 pa_tagstruct_gets(t, &name) < 0 ||
3230 !pa_tagstruct_eof(t)) {
3231 protocol_error(c);
3232 return;
3233 }
3234
3235 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3236 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
3237
3238 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
3239 playback_stream *s;
3240
3241 s = pa_idxset_get_by_index(c->output_streams, idx);
3242 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3243 CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3244
3245 pa_sink_input_set_name(s->sink_input, name);
3246
3247 } else {
3248 record_stream *s;
3249 pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
3250
3251 s = pa_idxset_get_by_index(c->record_streams, idx);
3252 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3253
3254 pa_source_output_set_name(s->source_output, name);
3255 }
3256
3257 pa_pstream_send_simple_ack(c->pstream, tag);
3258 }
3259
3260 static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3261 connection *c = CONNECTION(userdata);
3262 uint32_t idx;
3263
3264 connection_assert_ref(c);
3265 pa_assert(t);
3266
3267 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3268 !pa_tagstruct_eof(t)) {
3269 protocol_error(c);
3270 return;
3271 }
3272
3273 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3274
3275 if (command == PA_COMMAND_KILL_CLIENT) {
3276 pa_client *client;
3277
3278 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3279 CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
3280
3281 connection_ref(c);
3282 pa_client_kill(client);
3283
3284 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
3285 pa_sink_input *s;
3286
3287 s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3288 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3289
3290 connection_ref(c);
3291 pa_sink_input_kill(s);
3292 } else {
3293 pa_source_output *s;
3294
3295 pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
3296
3297 s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3298 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3299
3300 connection_ref(c);
3301 pa_source_output_kill(s);
3302 }
3303
3304 pa_pstream_send_simple_ack(c->pstream, tag);
3305 connection_unref(c);
3306 }
3307
3308 static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3309 connection *c = CONNECTION(userdata);
3310 pa_module *m;
3311 const char *name, *argument;
3312 pa_tagstruct *reply;
3313
3314 connection_assert_ref(c);
3315 pa_assert(t);
3316
3317 if (pa_tagstruct_gets(t, &name) < 0 ||
3318 pa_tagstruct_gets(t, &argument) < 0 ||
3319 !pa_tagstruct_eof(t)) {
3320 protocol_error(c);
3321 return;
3322 }
3323
3324 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3325 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
3326 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
3327
3328 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
3329 pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
3330 return;
3331 }
3332
3333 reply = reply_new(tag);
3334 pa_tagstruct_putu32(reply, m->index);
3335 pa_pstream_send_tagstruct(c->pstream, reply);
3336 }
3337
3338 static void command_unload_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3339 connection *c = CONNECTION(userdata);
3340 uint32_t idx;
3341 pa_module *m;
3342
3343 connection_assert_ref(c);
3344 pa_assert(t);
3345
3346 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3347 !pa_tagstruct_eof(t)) {
3348 protocol_error(c);
3349 return;
3350 }
3351
3352 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3353 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3354 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
3355
3356 pa_module_unload_request(m);
3357 pa_pstream_send_simple_ack(c->pstream, tag);
3358 }
3359
3360 static void command_add_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3361 connection *c = CONNECTION(userdata);
3362 const char *name, *module, *argument;
3363 uint32_t type;
3364 uint32_t idx;
3365 pa_tagstruct *reply;
3366
3367 connection_assert_ref(c);
3368 pa_assert(t);
3369
3370 if (pa_tagstruct_gets(t, &name) < 0 ||
3371 pa_tagstruct_getu32(t, &type) < 0 ||
3372 pa_tagstruct_gets(t, &module) < 0 ||
3373 pa_tagstruct_gets(t, &argument) < 0 ||
3374 !pa_tagstruct_eof(t)) {
3375 protocol_error(c);
3376 return;
3377 }
3378
3379 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3380 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
3381 CHECK_VALIDITY(c->pstream, type == 0 || type == 1, tag, PA_ERR_INVALID);
3382 CHECK_VALIDITY(c->pstream, module && *module && pa_utf8_valid(module), tag, PA_ERR_INVALID);
3383 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
3384
3385 if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &idx) < 0) {
3386 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
3387 return;
3388 }
3389
3390 reply = reply_new(tag);
3391 pa_tagstruct_putu32(reply, idx);
3392 pa_pstream_send_tagstruct(c->pstream, reply);
3393 }
3394
3395 static void command_remove_autoload(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3396 connection *c = CONNECTION(userdata);
3397 const char *name = NULL;
3398 uint32_t type, idx = PA_IDXSET_INVALID;
3399 int r;
3400
3401 connection_assert_ref(c);
3402 pa_assert(t);
3403
3404 if ((pa_tagstruct_getu32(t, &idx) < 0 &&
3405 (pa_tagstruct_gets(t, &name) < 0 ||
3406 pa_tagstruct_getu32(t, &type) < 0)) ||
3407 !pa_tagstruct_eof(t)) {
3408 protocol_error(c);
3409 return;
3410 }
3411
3412 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3413 CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID);
3414 CHECK_VALIDITY(c->pstream, !name || (*name && pa_utf8_valid(name) && (type == 0 || type == 1)), tag, PA_ERR_INVALID);
3415
3416 if (name)
3417 r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
3418 else
3419 r = pa_autoload_remove_by_index(c->protocol->core, idx);
3420
3421 CHECK_VALIDITY(c->pstream, r >= 0, tag, PA_ERR_NOENTITY);
3422
3423 pa_pstream_send_simple_ack(c->pstream, tag);
3424 }
3425
3426 static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) {
3427 pa_assert(t && e);
3428
3429 pa_tagstruct_putu32(t, e->index);
3430 pa_tagstruct_puts(t, e->name);
3431 pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1);
3432 pa_tagstruct_puts(t, e->module);
3433 pa_tagstruct_puts(t, e->argument);
3434 }
3435
3436 static void command_get_autoload_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3437 connection *c = CONNECTION(userdata);
3438 const pa_autoload_entry *a = NULL;
3439 uint32_t type, idx;
3440 const char *name;
3441 pa_tagstruct *reply;
3442
3443 connection_assert_ref(c);
3444 pa_assert(t);
3445
3446 if ((pa_tagstruct_getu32(t, &idx) < 0 &&
3447 (pa_tagstruct_gets(t, &name) < 0 ||
3448 pa_tagstruct_getu32(t, &type) < 0)) ||
3449 !pa_tagstruct_eof(t)) {
3450 protocol_error(c);
3451 return;
3452 }
3453
3454 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3455 CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID);
3456 CHECK_VALIDITY(c->pstream, !name || (*name && (type == 0 || type == 1) && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
3457
3458 if (name)
3459 a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
3460 else
3461 a = pa_autoload_get_by_index(c->protocol->core, idx);
3462
3463 CHECK_VALIDITY(c->pstream, a, tag, PA_ERR_NOENTITY);
3464
3465 reply = reply_new(tag);
3466 autoload_fill_tagstruct(reply, a);
3467 pa_pstream_send_tagstruct(c->pstream, reply);
3468 }
3469
3470 static void command_get_autoload_info_list(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3471 connection *c = CONNECTION(userdata);
3472 pa_tagstruct *reply;
3473
3474 connection_assert_ref(c);
3475 pa_assert(t);
3476
3477 if (!pa_tagstruct_eof(t)) {
3478 protocol_error(c);
3479 return;
3480 }
3481
3482 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3483
3484 reply = reply_new(tag);
3485
3486 if (c->protocol->core->autoload_hashmap) {
3487 pa_autoload_entry *a;
3488 void *state = NULL;
3489
3490 while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL)))
3491 autoload_fill_tagstruct(reply, a);
3492 }
3493
3494 pa_pstream_send_tagstruct(c->pstream, reply);
3495 }
3496
3497 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3498 connection *c = CONNECTION(userdata);
3499 uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
3500 const char *name = NULL;
3501
3502 connection_assert_ref(c);
3503 pa_assert(t);
3504
3505 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3506 pa_tagstruct_getu32(t, &idx_device) < 0 ||
3507 pa_tagstruct_gets(t, &name) < 0 ||
3508 !pa_tagstruct_eof(t)) {
3509 protocol_error(c);
3510 return;
3511 }
3512
3513 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3514 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3515 CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
3516
3517 if (command == PA_COMMAND_MOVE_SINK_INPUT) {
3518 pa_sink_input *si = NULL;
3519 pa_sink *sink = NULL;
3520
3521 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3522
3523 if (idx_device != PA_INVALID_INDEX)
3524 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
3525 else
3526 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
3527
3528 CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
3529
3530 if (pa_sink_input_move_to(si, sink, 0) < 0) {
3531 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
3532 return;
3533 }
3534 } else {
3535 pa_source_output *so = NULL;
3536 pa_source *source;
3537
3538 pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
3539
3540 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3541
3542 if (idx_device != PA_INVALID_INDEX)
3543 source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
3544 else
3545 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
3546
3547 CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
3548
3549 if (pa_source_output_move_to(so, source) < 0) {
3550 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
3551 return;
3552 }
3553 }
3554
3555 pa_pstream_send_simple_ack(c->pstream, tag);
3556 }
3557
3558 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3559 connection *c = CONNECTION(userdata);
3560 uint32_t idx = PA_INVALID_INDEX;
3561 const char *name = NULL;
3562 pa_bool_t b;
3563
3564 connection_assert_ref(c);
3565 pa_assert(t);
3566
3567 if (pa_tagstruct_getu32(t, &idx) < 0 ||
3568 pa_tagstruct_gets(t, &name) < 0 ||
3569 pa_tagstruct_get_boolean(t, &b) < 0 ||
3570 !pa_tagstruct_eof(t)) {
3571 protocol_error(c);
3572 return;
3573 }
3574
3575 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3576 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || !*name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
3577
3578 if (command == PA_COMMAND_SUSPEND_SINK) {
3579
3580 if (idx == PA_INVALID_INDEX && name && !*name) {
3581
3582 if (pa_sink_suspend_all(c->protocol->core, b) < 0) {
3583 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
3584 return;
3585 }
3586 } else {
3587 pa_sink *sink = NULL;
3588
3589 if (idx != PA_INVALID_INDEX)
3590 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3591 else
3592 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
3593
3594 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
3595
3596 if (pa_sink_suspend(sink, b) < 0) {
3597 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
3598 return;
3599 }
3600 }
3601 } else {
3602
3603 pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
3604
3605 if (idx == PA_INVALID_INDEX && name && !*name) {
3606
3607 if (pa_source_suspend_all(c->protocol->core, b) < 0) {
3608 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
3609 return;
3610 }
3611
3612 } else {
3613 pa_source *source;
3614
3615 if (idx != PA_INVALID_INDEX)
3616 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3617 else
3618 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
3619
3620 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
3621
3622 if (pa_source_suspend(source, b) < 0) {
3623 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
3624 return;
3625 }
3626 }
3627 }
3628
3629 pa_pstream_send_simple_ack(c->pstream, tag);
3630 }
3631
3632 /*** pstream callbacks ***/
3633
3634 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
3635 connection *c = CONNECTION(userdata);
3636
3637 pa_assert(p);
3638 pa_assert(packet);
3639 connection_assert_ref(c);
3640
3641 if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
3642 pa_log("invalid packet.");
3643 connection_unlink(c);
3644 }
3645 }
3646
3647 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) {
3648 connection *c = CONNECTION(userdata);
3649 output_stream *stream;
3650
3651 pa_assert(p);
3652 pa_assert(chunk);
3653 connection_assert_ref(c);
3654
3655 if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
3656 pa_log("client sent block for invalid stream.");
3657 /* Ignoring */
3658 return;
3659 }
3660
3661 if (playback_stream_isinstance(stream)) {
3662 playback_stream *ps = PLAYBACK_STREAM(stream);
3663
3664 if (seek != PA_SEEK_RELATIVE || offset != 0)
3665 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL);
3666
3667 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
3668
3669 } else {
3670 upload_stream *u = UPLOAD_STREAM(stream);
3671 size_t l;
3672
3673 if (!u->memchunk.memblock) {
3674 if (u->length == chunk->length) {
3675 u->memchunk = *chunk;
3676 pa_memblock_ref(u->memchunk.memblock);
3677 u->length = 0;
3678 } else {
3679 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
3680 u->memchunk.index = u->memchunk.length = 0;
3681 }
3682 }
3683
3684 pa_assert(u->memchunk.memblock);
3685
3686 l = u->length;
3687 if (l > chunk->length)
3688 l = chunk->length;
3689
3690
3691 if (l > 0) {
3692 void *src, *dst;
3693 dst = pa_memblock_acquire(u->memchunk.memblock);
3694 src = pa_memblock_acquire(chunk->memblock);
3695
3696 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
3697 (uint8_t*) src+chunk->index, l);
3698
3699 pa_memblock_release(u->memchunk.memblock);
3700 pa_memblock_release(chunk->memblock);
3701
3702 u->memchunk.length += l;
3703 u->length -= l;
3704 }
3705 }
3706 }
3707
3708 static void pstream_die_callback(pa_pstream *p, void *userdata) {
3709 connection *c = CONNECTION(userdata);
3710
3711 pa_assert(p);
3712 connection_assert_ref(c);
3713
3714 connection_unlink(c);
3715 pa_log_info("connection died.");
3716 }
3717
3718 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
3719 connection *c = CONNECTION(userdata);
3720
3721 pa_assert(p);
3722 connection_assert_ref(c);
3723
3724 send_memblock(c);
3725 }
3726
3727 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
3728 pa_thread_mq *q;
3729
3730 if (!(q = pa_thread_mq_get()))
3731 pa_pstream_send_revoke(p, block_id);
3732 else
3733 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
3734 }
3735
3736 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
3737 pa_thread_mq *q;
3738
3739 if (!(q = pa_thread_mq_get()))
3740 pa_pstream_send_release(p, block_id);
3741 else
3742 pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
3743 }
3744
3745 /*** client callbacks ***/
3746
3747 static void client_kill_cb(pa_client *c) {
3748 pa_assert(c);
3749
3750 connection_unlink(CONNECTION(c->userdata));
3751 }
3752
3753 /*** socket server callbacks ***/
3754
3755 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
3756 connection *c = CONNECTION(userdata);
3757
3758 pa_assert(m);
3759 pa_assert(tv);
3760 connection_assert_ref(c);
3761 pa_assert(c->auth_timeout_event == e);
3762
3763 if (!c->authorized)
3764 connection_unlink(c);
3765 }
3766
3767 static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, void *userdata) {
3768 pa_protocol_native *p = userdata;
3769 connection *c;
3770 char cname[256], pname[128];
3771
3772 pa_assert(s);
3773 pa_assert(io);
3774 pa_assert(p);
3775
3776 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
3777 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
3778 pa_iochannel_free(io);
3779 return;
3780 }
3781
3782 c = pa_msgobject_new(connection);
3783 c->parent.parent.free = connection_free;
3784 c->parent.process_msg = connection_process_msg;
3785
3786 c->authorized = p->public;
3787
3788 if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
3789 pa_log_info("Client authenticated by IP ACL.");
3790 c->authorized = TRUE;
3791 }
3792
3793 if (!c->authorized) {
3794 struct timeval tv;
3795 pa_gettimeofday(&tv);
3796 tv.tv_sec += AUTH_TIMEOUT;
3797 c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
3798 } else
3799 c->auth_timeout_event = NULL;
3800
3801 c->version = 8;
3802 c->protocol = p;
3803 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
3804 pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname);
3805 c->client = pa_client_new(p->core, __FILE__, cname);
3806 c->client->kill = client_kill_cb;
3807 c->client->userdata = c;
3808 c->client->module = p->module;
3809
3810 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
3811
3812 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
3813 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
3814 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
3815 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
3816 pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
3817 pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
3818
3819 c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
3820
3821 c->record_streams = pa_idxset_new(NULL, NULL);
3822 c->output_streams = pa_idxset_new(NULL, NULL);
3823
3824 c->rrobin_index = PA_IDXSET_INVALID;
3825 c->subscription = NULL;
3826
3827 pa_idxset_put(p->connections, c, NULL);
3828
3829 #ifdef HAVE_CREDS
3830 if (pa_iochannel_creds_supported(io))
3831 pa_iochannel_creds_enable(io);
3832
3833 #endif
3834 }
3835
3836 /*** module entry points ***/
3837
3838 static int load_key(pa_protocol_native*p, const char*fn) {
3839 pa_assert(p);
3840
3841 p->auth_cookie_in_property = FALSE;
3842
3843 if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) {
3844 pa_log_info("using already loaded auth cookie.");
3845 pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
3846 p->auth_cookie_in_property = TRUE;
3847 return 0;
3848 }
3849
3850 if (!fn)
3851 fn = PA_NATIVE_COOKIE_FILE;
3852
3853 if (pa_authkey_load_auto(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0)
3854 return -1;
3855
3856 pa_log_info("loading cookie from disk.");
3857
3858 if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0)
3859 p->auth_cookie_in_property = TRUE;
3860
3861 return 0;
3862 }
3863
3864 static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_modargs *ma) {
3865 pa_protocol_native *p;
3866 pa_bool_t public = FALSE;
3867 const char *acl;
3868
3869 pa_assert(c);
3870 pa_assert(ma);
3871
3872 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) {
3873 pa_log("auth-anonymous= expects a boolean argument.");
3874 return NULL;
3875 }
3876
3877 p = pa_xnew(pa_protocol_native, 1);
3878 p->core = c;
3879 p->module = m;
3880 p->public = public;
3881 p->server = NULL;
3882 p->auth_ip_acl = NULL;
3883
3884 #ifdef HAVE_CREDS
3885 {
3886 pa_bool_t a = 1;
3887 if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) {
3888 pa_log("auth-group-enabled= expects a boolean argument.");
3889 return NULL;
3890 }
3891 p->auth_group = a ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", c->is_system_instance ? PA_ACCESS_GROUP : NULL)) : NULL;
3892
3893 if (p->auth_group)
3894 pa_log_info("Allowing access to group '%s'.", p->auth_group);
3895 }
3896 #endif
3897
3898
3899 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
3900
3901 if (!(p->auth_ip_acl = pa_ip_acl_new(acl))) {
3902 pa_log("Failed to parse IP ACL '%s'", acl);
3903 goto fail;
3904 }
3905 }
3906
3907 if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
3908 goto fail;
3909
3910 p->connections = pa_idxset_new(NULL, NULL);
3911
3912 return p;
3913
3914 fail:
3915 #ifdef HAVE_CREDS
3916 pa_xfree(p->auth_group);
3917 #endif
3918 if (p->auth_ip_acl)
3919 pa_ip_acl_free(p->auth_ip_acl);
3920 pa_xfree(p);
3921 return NULL;
3922 }
3923
3924 pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
3925 char t[256];
3926 pa_protocol_native *p;
3927
3928 if (!(p = protocol_new_internal(core, m, ma)))
3929 return NULL;
3930
3931 p->server = server;
3932 pa_socket_server_set_callback(p->server, on_connection, p);
3933
3934 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
3935 pa_strlist *l;
3936 l = pa_property_get(core, PA_NATIVE_SERVER_PROPERTY_NAME);
3937 l = pa_strlist_prepend(l, t);
3938 pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
3939 }
3940
3941 return p;
3942 }
3943
3944 void pa_protocol_native_free(pa_protocol_native *p) {
3945 connection *c;
3946 pa_assert(p);
3947
3948 while ((c = pa_idxset_first(p->connections, NULL)))
3949 connection_unlink(c);
3950 pa_idxset_free(p->connections, NULL, NULL);
3951
3952 if (p->server) {
3953 char t[256];
3954
3955 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
3956 pa_strlist *l;
3957 l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
3958 l = pa_strlist_remove(l, t);
3959
3960 if (l)
3961 pa_property_replace(p->core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
3962 else
3963 pa_property_remove(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
3964 }
3965
3966 pa_socket_server_unref(p->server);
3967 }
3968
3969 if (p->auth_cookie_in_property)
3970 pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
3971
3972 if (p->auth_ip_acl)
3973 pa_ip_acl_free(p->auth_ip_acl);
3974
3975 #ifdef HAVE_CREDS
3976 pa_xfree(p->auth_group);
3977 #endif
3978 pa_xfree(p);
3979 }
3980
3981 pa_protocol_native* pa_protocol_native_new_iochannel(
3982 pa_core*core,
3983 pa_iochannel *io,
3984 pa_module *m,
3985 pa_modargs *ma) {
3986
3987 pa_protocol_native *p;
3988
3989 if (!(p = protocol_new_internal(core, m, ma)))
3990 return NULL;
3991
3992 on_connection(NULL, io, p);
3993
3994 return p;
3995 }