implement hook_source_ouput_new. For this I modified the pa_source_output_new constru...
[pulseaudio.git] / src / pulsecore / protocol-native.c
blob0b79892c58ebb7839c8a568cebe76b73e004d29f
1 /* $Id$ */
3 /***
4 This file is part of PulseAudio.
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <string.h>
27 #include <stdio.h>
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <unistd.h>
32 #include <pulse/timeval.h>
33 #include <pulse/version.h>
34 #include <pulse/utf8.h>
35 #include <pulse/util.h>
36 #include <pulse/xmalloc.h>
38 #include <pulsecore/native-common.h>
39 #include <pulsecore/packet.h>
40 #include <pulsecore/client.h>
41 #include <pulsecore/source-output.h>
42 #include <pulsecore/sink-input.h>
43 #include <pulsecore/pstream.h>
44 #include <pulsecore/tagstruct.h>
45 #include <pulsecore/pdispatch.h>
46 #include <pulsecore/pstream-util.h>
47 #include <pulsecore/authkey.h>
48 #include <pulsecore/namereg.h>
49 #include <pulsecore/core-scache.h>
50 #include <pulsecore/core-subscribe.h>
51 #include <pulsecore/log.h>
52 #include <pulsecore/autoload.h>
53 #include <pulsecore/authkey-prop.h>
54 #include <pulsecore/strlist.h>
55 #include <pulsecore/props.h>
56 #include <pulsecore/sample-util.h>
57 #include <pulsecore/llist.h>
58 #include <pulsecore/creds.h>
59 #include <pulsecore/core-util.h>
60 #include <pulsecore/ipacl.h>
62 #include "protocol-native.h"
64 /* Kick a client if it doesn't authenticate within this time */
65 #define AUTH_TIMEOUT 60
67 /* Don't accept more connection than this */
68 #define MAX_CONNECTIONS 64
70 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
72 struct connection;
73 struct pa_protocol_native;
75 struct record_stream {
76 struct connection *connection;
77 uint32_t index;
78 pa_source_output *source_output;
79 pa_memblockq *memblockq;
80 size_t fragment_size;
83 struct playback_stream {
84 int type;
85 struct connection *connection;
86 uint32_t index;
87 pa_sink_input *sink_input;
88 pa_memblockq *memblockq;
89 size_t requested_bytes;
90 int drain_request;
91 uint32_t drain_tag;
92 uint32_t syncid;
93 int underrun;
95 /* Sync group members */
96 PA_LLIST_FIELDS(struct playback_stream);
99 struct upload_stream {
100 int type;
101 struct connection *connection;
102 uint32_t index;
103 pa_memchunk memchunk;
104 size_t length;
105 char *name;
106 pa_sample_spec sample_spec;
107 pa_channel_map channel_map;
110 struct output_stream {
111 int type;
114 enum {
115 UPLOAD_STREAM,
116 PLAYBACK_STREAM
119 struct connection {
120 int authorized;
121 uint32_t version;
122 pa_protocol_native *protocol;
123 pa_client *client;
124 pa_pstream *pstream;
125 pa_pdispatch *pdispatch;
126 pa_idxset *record_streams, *output_streams;
127 uint32_t rrobin_index;
128 pa_subscription *subscription;
129 pa_time_event *auth_timeout_event;
132 struct pa_protocol_native {
133 pa_module *module;
134 int public;
135 pa_core *core;
136 pa_socket_server *server;
137 pa_idxset *connections;
138 uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
139 int auth_cookie_in_property;
140 #ifdef HAVE_CREDS
141 char *auth_group;
142 #endif
143 pa_ip_acl *auth_ip_acl;
146 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk);
147 static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length);
148 static void sink_input_kill_cb(pa_sink_input *i);
149 static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i);
151 static void request_bytes(struct playback_stream*s);
153 static void source_output_kill_cb(pa_source_output *o);
154 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
155 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
157 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
158 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
159 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
160 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
161 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
162 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
163 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
164 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
165 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
166 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
167 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
168 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
169 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
170 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
171 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
172 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
173 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
174 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
175 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
176 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
177 static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
178 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
179 static void command_flush_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
180 static void command_trigger_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
181 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
182 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
183 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
184 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
185 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
186 static void command_add_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
187 static void command_remove_autoload(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
188 static void command_get_autoload_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
189 static void command_get_autoload_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
190 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
191 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
192 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
194 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
195 [PA_COMMAND_ERROR] = NULL,
196 [PA_COMMAND_TIMEOUT] = NULL,
197 [PA_COMMAND_REPLY] = NULL,
198 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
199 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
200 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
201 [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
202 [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
203 [PA_COMMAND_AUTH] = command_auth,
204 [PA_COMMAND_REQUEST] = NULL,
205 [PA_COMMAND_EXIT] = command_exit,
206 [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
207 [PA_COMMAND_LOOKUP_SINK] = command_lookup,
208 [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
209 [PA_COMMAND_STAT] = command_stat,
210 [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
211 [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
212 [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
213 [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
214 [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
215 [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
216 [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
217 [PA_COMMAND_GET_SINK_INFO] = command_get_info,
218 [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
219 [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
220 [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
221 [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
222 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
223 [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
224 [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
225 [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
226 [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
227 [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
228 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
229 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
230 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
231 [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
232 [PA_COMMAND_SUBSCRIBE] = command_subscribe,
234 [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
235 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
236 [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
238 [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
239 [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
241 [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
242 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream,
243 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream,
244 [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream,
246 [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
247 [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
249 [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
250 [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
251 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
252 [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
253 [PA_COMMAND_KILL_CLIENT] = command_kill,
254 [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
255 [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
256 [PA_COMMAND_LOAD_MODULE] = command_load_module,
257 [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
258 [PA_COMMAND_GET_AUTOLOAD_INFO] = command_get_autoload_info,
259 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = command_get_autoload_info_list,
260 [PA_COMMAND_ADD_AUTOLOAD] = command_add_autoload,
261 [PA_COMMAND_REMOVE_AUTOLOAD] = command_remove_autoload,
263 [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
264 [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream
267 /* structure management */
269 static struct upload_stream* upload_stream_new(
270 struct connection *c,
271 const pa_sample_spec *ss,
272 const pa_channel_map *map,
273 const char *name, size_t length) {
275 struct upload_stream *s;
276 assert(c && ss && name && length);
278 s = pa_xnew(struct upload_stream, 1);
279 s->type = UPLOAD_STREAM;
280 s->connection = c;
281 s->sample_spec = *ss;
282 s->channel_map = *map;
283 s->name = pa_xstrdup(name);
285 s->memchunk.memblock = NULL;
286 s->memchunk.index = 0;
287 s->memchunk.length = 0;
289 s->length = length;
291 pa_idxset_put(c->output_streams, s, &s->index);
292 return s;
295 static void upload_stream_free(struct upload_stream *o) {
296 assert(o && o->connection);
298 pa_idxset_remove_by_data(o->connection->output_streams, o, NULL);
300 pa_xfree(o->name);
302 if (o->memchunk.memblock)
303 pa_memblock_unref(o->memchunk.memblock);
305 pa_xfree(o);
308 static struct record_stream* record_stream_new(
309 struct connection *c,
310 pa_source *source,
311 const pa_sample_spec *ss,
312 const pa_channel_map *map,
313 const char *name,
314 size_t maxlength,
315 size_t fragment_size) {
317 struct record_stream *s;
318 pa_source_output *source_output;
319 size_t base;
320 pa_source_output_new_data data;
322 assert(c && source && ss && name && maxlength);
324 pa_source_output_new_data_init(&data);
325 data.source = source;
326 data.driver = __FILE__;
327 data.name = name;
328 pa_source_output_new_data_set_sample_spec(&data, ss);
329 pa_source_output_new_data_set_channel_map(&data, map);
330 data.module = c->protocol->module;
331 data.client = c->client;
333 if (!(source_output = pa_source_output_new(source->core, &data, 0)))
334 return NULL;
336 s = pa_xnew(struct record_stream, 1);
337 s->connection = c;
338 s->source_output = source_output;
339 s->source_output->push = source_output_push_cb;
340 s->source_output->kill = source_output_kill_cb;
341 s->source_output->get_latency = source_output_get_latency_cb;
342 s->source_output->userdata = s;
344 s->memblockq = pa_memblockq_new(
346 maxlength,
348 base = pa_frame_size(ss),
351 NULL,
352 c->protocol->core->memblock_stat);
353 assert(s->memblockq);
355 s->fragment_size = (fragment_size/base)*base;
356 if (!s->fragment_size)
357 s->fragment_size = base;
359 pa_idxset_put(c->record_streams, s, &s->index);
360 return s;
363 static void record_stream_free(struct record_stream* r) {
364 assert(r && r->connection);
366 pa_idxset_remove_by_data(r->connection->record_streams, r, NULL);
367 pa_source_output_disconnect(r->source_output);
368 pa_source_output_unref(r->source_output);
369 pa_memblockq_free(r->memblockq);
370 pa_xfree(r);
373 static struct playback_stream* playback_stream_new(
374 struct connection *c,
375 pa_sink *sink,
376 const pa_sample_spec *ss,
377 const pa_channel_map *map,
378 const char *name,
379 size_t maxlength,
380 size_t tlength,
381 size_t prebuf,
382 size_t minreq,
383 pa_cvolume *volume,
384 uint32_t syncid) {
386 struct playback_stream *s, *ssync;
387 pa_sink_input *sink_input;
388 pa_memblock *silence;
389 uint32_t idx;
390 int64_t start_index;
391 pa_sink_input_new_data data;
393 assert(c && sink && ss && name && maxlength);
395 /* Find syncid group */
396 for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
398 if (ssync->type != PLAYBACK_STREAM)
399 continue;
401 if (ssync->syncid == syncid)
402 break;
405 /* Synced streams must connect to the same sink */
406 if (ssync && ssync->sink_input->sink != sink)
407 return NULL;
409 pa_sink_input_new_data_init(&data);
410 data.sink = sink;
411 data.driver = __FILE__;
412 data.name = name;
413 pa_sink_input_new_data_set_sample_spec(&data, ss);
414 pa_sink_input_new_data_set_channel_map(&data, map);
415 pa_sink_input_new_data_set_volume(&data, volume);
416 data.module = c->protocol->module;
417 data.client = c->client;
419 if (!(sink_input = pa_sink_input_new(sink->core, &data, 0)))
420 return NULL;
422 s = pa_xnew(struct playback_stream, 1);
423 s->type = PLAYBACK_STREAM;
424 s->connection = c;
425 s->syncid = syncid;
426 s->sink_input = sink_input;
427 s->underrun = 1;
429 s->sink_input->peek = sink_input_peek_cb;
430 s->sink_input->drop = sink_input_drop_cb;
431 s->sink_input->kill = sink_input_kill_cb;
432 s->sink_input->get_latency = sink_input_get_latency_cb;
433 s->sink_input->userdata = s;
435 if (ssync) {
436 /* Sync id found, now find head of list */
437 PA_LLIST_FIND_HEAD(struct playback_stream, ssync, &ssync);
439 /* Prepend ourselves */
440 PA_LLIST_PREPEND(struct playback_stream, ssync, s);
442 /* Set our start index to the current read index of the other grozp member(s) */
443 assert(ssync->next);
444 start_index = pa_memblockq_get_read_index(ssync->next->memblockq);
445 } else {
446 /* This ia a new sync group */
447 PA_LLIST_INIT(struct playback_stream, s);
448 start_index = 0;
451 silence = pa_silence_memblock_new(ss, 0, c->protocol->core->memblock_stat);
453 s->memblockq = pa_memblockq_new(
454 start_index,
455 maxlength,
456 tlength,
457 pa_frame_size(ss),
458 prebuf,
459 minreq,
460 silence,
461 c->protocol->core->memblock_stat);
463 pa_memblock_unref(silence);
465 s->requested_bytes = 0;
466 s->drain_request = 0;
468 pa_idxset_put(c->output_streams, s, &s->index);
470 return s;
473 static void playback_stream_free(struct playback_stream* p) {
474 struct playback_stream *head;
475 assert(p && p->connection);
477 if (p->drain_request)
478 pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERR_NOENTITY);
480 PA_LLIST_FIND_HEAD(struct playback_stream, p, &head);
481 PA_LLIST_REMOVE(struct playback_stream, head, p);
483 pa_idxset_remove_by_data(p->connection->output_streams, p, NULL);
484 pa_sink_input_disconnect(p->sink_input);
485 pa_sink_input_unref(p->sink_input);
486 pa_memblockq_free(p->memblockq);
487 pa_xfree(p);
490 static void connection_free(struct connection *c) {
491 struct record_stream *r;
492 struct output_stream *o;
493 assert(c && c->protocol);
495 pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
496 while ((r = pa_idxset_first(c->record_streams, NULL)))
497 record_stream_free(r);
498 pa_idxset_free(c->record_streams, NULL, NULL);
500 while ((o = pa_idxset_first(c->output_streams, NULL)))
501 if (o->type == PLAYBACK_STREAM)
502 playback_stream_free((struct playback_stream*) o);
503 else
504 upload_stream_free((struct upload_stream*) o);
505 pa_idxset_free(c->output_streams, NULL, NULL);
507 pa_pdispatch_unref(c->pdispatch);
508 pa_pstream_close(c->pstream);
509 pa_pstream_unref(c->pstream);
510 pa_client_free(c->client);
512 if (c->subscription)
513 pa_subscription_free(c->subscription);
515 if (c->auth_timeout_event)
516 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
518 pa_xfree(c);
521 static void request_bytes(struct playback_stream *s) {
522 pa_tagstruct *t;
523 size_t l;
524 assert(s);
526 if (!(l = pa_memblockq_missing(s->memblockq)))
527 return;
529 if (l <= s->requested_bytes)
530 return;
532 l -= s->requested_bytes;
534 if (l < pa_memblockq_get_minreq(s->memblockq))
535 return;
537 s->requested_bytes += l;
539 t = pa_tagstruct_new(NULL, 0);
540 assert(t);
541 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
542 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
543 pa_tagstruct_putu32(t, s->index);
544 pa_tagstruct_putu32(t, l);
545 pa_pstream_send_tagstruct(s->connection->pstream, t);
547 /* pa_log(__FILE__": Requesting %u bytes", l); */
550 static void send_memblock(struct connection *c) {
551 uint32_t start;
552 struct record_stream *r;
554 start = PA_IDXSET_INVALID;
555 for (;;) {
556 pa_memchunk chunk;
558 if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index)))
559 return;
561 if (start == PA_IDXSET_INVALID)
562 start = c->rrobin_index;
563 else if (start == c->rrobin_index)
564 return;
566 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
567 pa_memchunk schunk = chunk;
569 if (schunk.length > r->fragment_size)
570 schunk.length = r->fragment_size;
572 pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
573 pa_memblockq_drop(r->memblockq, &chunk, schunk.length);
574 pa_memblock_unref(schunk.memblock);
576 return;
581 static void send_playback_stream_killed(struct playback_stream *p) {
582 pa_tagstruct *t;
583 assert(p);
585 t = pa_tagstruct_new(NULL, 0);
586 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
587 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
588 pa_tagstruct_putu32(t, p->index);
589 pa_pstream_send_tagstruct(p->connection->pstream, t);
592 static void send_record_stream_killed(struct record_stream *r) {
593 pa_tagstruct *t;
594 assert(r);
596 t = pa_tagstruct_new(NULL, 0);
597 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
598 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
599 pa_tagstruct_putu32(t, r->index);
600 pa_pstream_send_tagstruct(r->connection->pstream, t);
603 /*** sinkinput callbacks ***/
605 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
606 struct playback_stream *s;
607 assert(i && i->userdata && chunk);
608 s = i->userdata;
610 if (pa_memblockq_get_length(s->memblockq) <= 0 && !s->underrun) {
611 pa_tagstruct *t;
613 /* Report that we're empty */
615 t = pa_tagstruct_new(NULL, 0);
616 pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
617 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
618 pa_tagstruct_putu32(t, s->index);
619 pa_pstream_send_tagstruct(s->connection->pstream, t);
621 s->underrun = 1;
624 if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
625 /* pa_log(__FILE__": peek: failure"); */
626 return -1;
629 /* pa_log(__FILE__": peek: %u", chunk->length); */
631 return 0;
634 static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
635 struct playback_stream *s;
636 assert(i && i->userdata && length);
637 s = i->userdata;
639 pa_memblockq_drop(s->memblockq, chunk, length);
641 request_bytes(s);
643 if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) {
644 pa_pstream_send_simple_ack(s->connection->pstream, s->drain_tag);
645 s->drain_request = 0;
648 /* pa_log(__FILE__": after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */
651 static void sink_input_kill_cb(pa_sink_input *i) {
652 assert(i && i->userdata);
653 send_playback_stream_killed((struct playback_stream *) i->userdata);
654 playback_stream_free((struct playback_stream *) i->userdata);
657 static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) {
658 struct playback_stream *s;
659 assert(i && i->userdata);
660 s = i->userdata;
662 /*pa_log(__FILE__": get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
664 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec);
667 /*** source_output callbacks ***/
669 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
670 struct record_stream *s;
671 assert(o && o->userdata && chunk);
672 s = o->userdata;
674 if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
675 pa_log_warn(__FILE__": Failed to push data into output queue.");
676 return;
679 if (!pa_pstream_is_pending(s->connection->pstream))
680 send_memblock(s->connection);
683 static void source_output_kill_cb(pa_source_output *o) {
684 assert(o && o->userdata);
685 send_record_stream_killed((struct record_stream *) o->userdata);
686 record_stream_free((struct record_stream *) o->userdata);
689 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
690 struct record_stream *s;
691 assert(o && o->userdata);
692 s = o->userdata;
694 /*pa_log(__FILE__": get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
696 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
699 /*** pdispatch callbacks ***/
701 static void protocol_error(struct connection *c) {
702 pa_log(__FILE__": protocol error, kicking client");
703 connection_free(c);
706 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
707 if (!(expression)) { \
708 pa_pstream_send_error((pstream), (tag), (error)); \
709 return; \
711 } while(0);
713 static pa_tagstruct *reply_new(uint32_t tag) {
714 pa_tagstruct *reply;
716 reply = pa_tagstruct_new(NULL, 0);
717 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
718 pa_tagstruct_putu32(reply, tag);
719 return reply;
722 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) {
723 struct connection *c = userdata;
724 struct playback_stream *s;
725 uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid;
726 const char *name, *sink_name;
727 pa_sample_spec ss;
728 pa_channel_map map;
729 pa_tagstruct *reply;
730 pa_sink *sink;
731 pa_cvolume volume;
732 int corked;
734 assert(c && t && c->protocol && c->protocol->core);
736 if (pa_tagstruct_get(
738 PA_TAG_STRING, &name,
739 PA_TAG_SAMPLE_SPEC, &ss,
740 PA_TAG_CHANNEL_MAP, &map,
741 PA_TAG_U32, &sink_index,
742 PA_TAG_STRING, &sink_name,
743 PA_TAG_U32, &maxlength,
744 PA_TAG_BOOLEAN, &corked,
745 PA_TAG_U32, &tlength,
746 PA_TAG_U32, &prebuf,
747 PA_TAG_U32, &minreq,
748 PA_TAG_U32, &syncid,
749 PA_TAG_CVOLUME, &volume,
750 PA_TAG_INVALID) < 0 ||
751 !pa_tagstruct_eof(t) ||
752 !name) {
753 protocol_error(c);
754 return;
757 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
758 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
759 CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
760 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
761 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
762 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
763 CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
764 CHECK_VALIDITY(c->pstream, maxlength > 0 && maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
766 if (sink_index != PA_INVALID_INDEX)
767 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
768 else
769 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
771 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
773 s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume, syncid);
774 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
776 pa_sink_input_cork(s->sink_input, corked);
778 reply = reply_new(tag);
779 pa_tagstruct_putu32(reply, s->index);
780 assert(s->sink_input);
781 pa_tagstruct_putu32(reply, s->sink_input->index);
782 pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq));
784 if (c->version >= 9) {
785 /* Since 0.9 we support sending the buffer metrics back to the client */
787 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
788 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_tlength(s->memblockq));
789 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq));
790 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq));
793 pa_pstream_send_tagstruct(c->pstream, reply);
794 request_bytes(s);
797 static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
798 struct connection *c = userdata;
799 uint32_t channel;
800 assert(c && t);
802 if (pa_tagstruct_getu32(t, &channel) < 0 ||
803 !pa_tagstruct_eof(t)) {
804 protocol_error(c);
805 return;
808 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
810 if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) {
811 struct playback_stream *s;
812 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != PLAYBACK_STREAM)) {
813 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
814 return;
817 playback_stream_free(s);
818 } else if (command == PA_COMMAND_DELETE_RECORD_STREAM) {
819 struct record_stream *s;
820 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
821 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
822 return;
825 record_stream_free(s);
826 } else {
827 struct upload_stream *s;
828 assert(command == PA_COMMAND_DELETE_UPLOAD_STREAM);
829 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) {
830 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
831 return;
834 upload_stream_free(s);
837 pa_pstream_send_simple_ack(c->pstream, tag);
840 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) {
841 struct connection *c = userdata;
842 struct record_stream *s;
843 uint32_t maxlength, fragment_size;
844 uint32_t source_index;
845 const char *name, *source_name;
846 pa_sample_spec ss;
847 pa_channel_map map;
848 pa_tagstruct *reply;
849 pa_source *source;
850 int corked;
851 assert(c && t && c->protocol && c->protocol->core);
853 if (pa_tagstruct_gets(t, &name) < 0 ||
854 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
855 pa_tagstruct_get_channel_map(t, &map) < 0 ||
856 pa_tagstruct_getu32(t, &source_index) < 0 ||
857 pa_tagstruct_gets(t, &source_name) < 0 ||
858 pa_tagstruct_getu32(t, &maxlength) < 0 ||
859 pa_tagstruct_get_boolean(t, &corked) < 0 ||
860 pa_tagstruct_getu32(t, &fragment_size) < 0 ||
861 !pa_tagstruct_eof(t)) {
862 protocol_error(c);
863 return;
866 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
867 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
868 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
869 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
870 CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID);
871 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
872 CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
874 if (source_index != PA_INVALID_INDEX)
875 source = pa_idxset_get_by_index(c->protocol->core->sources, source_index);
876 else
877 source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1);
879 CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
881 s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size);
882 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
884 pa_source_output_cork(s->source_output, corked);
886 reply = reply_new(tag);
887 pa_tagstruct_putu32(reply, s->index);
888 assert(s->source_output);
889 pa_tagstruct_putu32(reply, s->source_output->index);
891 if (c->version >= 9) {
892 /* Since 0.9 we support sending the buffer metrics back to the client */
894 pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
895 pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size);
898 pa_pstream_send_tagstruct(c->pstream, reply);
901 static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
902 struct connection *c = userdata;
903 assert(c && t);
905 if (!pa_tagstruct_eof(t)) {
906 protocol_error(c);
907 return;
910 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
912 assert(c->protocol && c->protocol->core && c->protocol->core->mainloop);
913 c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0);
914 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
917 static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
918 struct connection *c = userdata;
919 const void*cookie;
920 pa_tagstruct *reply;
921 assert(c && t);
923 if (pa_tagstruct_getu32(t, &c->version) < 0 ||
924 pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
925 !pa_tagstruct_eof(t)) {
926 protocol_error(c);
927 return;
930 /* Minimum supported version */
931 if (c->version < 8) {
932 pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
933 return;
936 if (!c->authorized) {
937 int success = 0;
939 #ifdef HAVE_CREDS
940 const pa_creds *creds;
942 if ((creds = pa_pdispatch_creds(pd))) {
943 if (creds->uid == getuid())
944 success = 1;
945 else if (c->protocol->auth_group) {
946 int r;
947 gid_t gid;
949 if ((gid = pa_get_gid_of_group(c->protocol->auth_group)) == (gid_t) -1)
950 pa_log_warn(__FILE__": failed to get GID of group '%s'", c->protocol->auth_group);
951 else if (gid == creds->gid)
952 success = 1;
954 if (!success) {
955 if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0)
956 pa_log_warn(__FILE__": failed to check group membership.");
957 else if (r > 0)
958 success = 1;
962 pa_log_info(__FILE__": Got credentials: uid=%lu gid=%lu success=%i",
963 (unsigned long) creds->uid,
964 (unsigned long) creds->gid,
965 success);
967 #endif
969 if (!success && memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
970 success = 1;
972 if (!success) {
973 pa_log_warn(__FILE__": Denied access to client with invalid authorization data.");
974 pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
975 return;
978 c->authorized = 1;
979 if (c->auth_timeout_event) {
980 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
981 c->auth_timeout_event = NULL;
985 reply = reply_new(tag);
986 pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION);
987 pa_pstream_send_tagstruct(c->pstream, reply);
990 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) {
991 struct connection *c = userdata;
992 const char *name;
993 assert(c && t);
995 if (pa_tagstruct_gets(t, &name) < 0 ||
996 !pa_tagstruct_eof(t)) {
997 protocol_error(c);
998 return;
1001 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1003 pa_client_set_name(c->client, name);
1004 pa_pstream_send_simple_ack(c->pstream, tag);
1007 static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1008 struct connection *c = userdata;
1009 const char *name;
1010 uint32_t idx = PA_IDXSET_INVALID;
1011 assert(c && t);
1013 if (pa_tagstruct_gets(t, &name) < 0 ||
1014 !pa_tagstruct_eof(t)) {
1015 protocol_error(c);
1016 return;
1019 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1020 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1022 if (command == PA_COMMAND_LOOKUP_SINK) {
1023 pa_sink *sink;
1024 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1)))
1025 idx = sink->index;
1026 } else {
1027 pa_source *source;
1028 assert(command == PA_COMMAND_LOOKUP_SOURCE);
1029 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1)))
1030 idx = source->index;
1033 if (idx == PA_IDXSET_INVALID)
1034 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1035 else {
1036 pa_tagstruct *reply;
1037 reply = reply_new(tag);
1038 pa_tagstruct_putu32(reply, idx);
1039 pa_pstream_send_tagstruct(c->pstream, reply);
1043 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) {
1044 struct connection *c = userdata;
1045 uint32_t idx;
1046 struct playback_stream *s;
1047 assert(c && t);
1049 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1050 !pa_tagstruct_eof(t)) {
1051 protocol_error(c);
1052 return;
1055 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1056 s = pa_idxset_get_by_index(c->output_streams, idx);
1057 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1058 CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
1060 s->drain_request = 0;
1062 pa_memblockq_prebuf_disable(s->memblockq);
1064 if (!pa_memblockq_is_readable(s->memblockq)) {
1065 /* pa_log("immediate drain: %u", pa_memblockq_get_length(s->memblockq)); */
1066 pa_pstream_send_simple_ack(c->pstream, tag);
1067 } else {
1068 /* pa_log("slow drain triggered"); */
1069 s->drain_request = 1;
1070 s->drain_tag = tag;
1072 pa_sink_notify(s->sink_input->sink);
1076 static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1077 struct connection *c = userdata;
1078 pa_tagstruct *reply;
1079 assert(c && t);
1081 if (!pa_tagstruct_eof(t)) {
1082 protocol_error(c);
1083 return;
1086 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1088 reply = reply_new(tag);
1089 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total);
1090 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total_size);
1091 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated);
1092 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated_size);
1093 pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core));
1094 pa_pstream_send_tagstruct(c->pstream, reply);
1097 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) {
1098 struct connection *c = userdata;
1099 pa_tagstruct *reply;
1100 struct playback_stream *s;
1101 struct timeval tv, now;
1102 uint32_t idx;
1103 pa_usec_t latency;
1104 assert(c && t);
1106 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1107 pa_tagstruct_get_timeval(t, &tv) < 0 ||
1108 !pa_tagstruct_eof(t)) {
1109 protocol_error(c);
1110 return;
1113 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1114 s = pa_idxset_get_by_index(c->output_streams, idx);
1115 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1116 CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
1118 reply = reply_new(tag);
1120 latency = pa_sink_get_latency(s->sink_input->sink);
1121 if (s->sink_input->resampled_chunk.memblock)
1122 latency += pa_bytes_to_usec(s->sink_input->resampled_chunk.length, &s->sink_input->sample_spec);
1123 pa_tagstruct_put_usec(reply, latency);
1125 pa_tagstruct_put_usec(reply, 0);
1126 pa_tagstruct_put_boolean(reply, s->sink_input->state == PA_SINK_INPUT_RUNNING);
1127 pa_tagstruct_put_timeval(reply, &tv);
1128 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
1129 pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
1130 pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
1131 pa_pstream_send_tagstruct(c->pstream, reply);
1134 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) {
1135 struct connection *c = userdata;
1136 pa_tagstruct *reply;
1137 struct record_stream *s;
1138 struct timeval tv, now;
1139 uint32_t idx;
1140 assert(c && t);
1142 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1143 pa_tagstruct_get_timeval(t, &tv) < 0 ||
1144 !pa_tagstruct_eof(t)) {
1145 protocol_error(c);
1146 return;
1149 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1150 s = pa_idxset_get_by_index(c->record_streams, idx);
1151 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1153 reply = reply_new(tag);
1154 pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
1155 pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
1156 pa_tagstruct_put_boolean(reply, 0);
1157 pa_tagstruct_put_timeval(reply, &tv);
1158 pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
1159 pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
1160 pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
1161 pa_pstream_send_tagstruct(c->pstream, reply);
1164 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) {
1165 struct connection *c = userdata;
1166 struct upload_stream *s;
1167 uint32_t length;
1168 const char *name;
1169 pa_sample_spec ss;
1170 pa_channel_map map;
1171 pa_tagstruct *reply;
1172 assert(c && t && c->protocol && c->protocol->core);
1174 if (pa_tagstruct_gets(t, &name) < 0 ||
1175 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
1176 pa_tagstruct_get_channel_map(t, &map) < 0 ||
1177 pa_tagstruct_getu32(t, &length) < 0 ||
1178 !pa_tagstruct_eof(t)) {
1179 protocol_error(c);
1180 return;
1183 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1184 CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1185 CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1186 CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
1187 CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
1188 CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
1189 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1191 s = upload_stream_new(c, &ss, &map, name, length);
1192 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
1194 reply = reply_new(tag);
1195 pa_tagstruct_putu32(reply, s->index);
1196 pa_tagstruct_putu32(reply, length);
1197 pa_pstream_send_tagstruct(c->pstream, reply);
1200 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) {
1201 struct connection *c = userdata;
1202 uint32_t channel;
1203 struct upload_stream *s;
1204 uint32_t idx;
1205 assert(c && t);
1207 if (pa_tagstruct_getu32(t, &channel) < 0 ||
1208 !pa_tagstruct_eof(t)) {
1209 protocol_error(c);
1210 return;
1213 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1215 s = pa_idxset_get_by_index(c->output_streams, channel);
1216 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1217 CHECK_VALIDITY(c->pstream, s->type == UPLOAD_STREAM, tag, PA_ERR_NOENTITY);
1219 if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx) < 0)
1220 pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
1221 else
1222 pa_pstream_send_simple_ack(c->pstream, tag);
1224 upload_stream_free(s);
1227 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) {
1228 struct connection *c = userdata;
1229 uint32_t sink_index;
1230 pa_volume_t volume;
1231 pa_sink *sink;
1232 const char *name, *sink_name;
1233 assert(c && t);
1235 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
1236 pa_tagstruct_gets(t, &sink_name) < 0 ||
1237 pa_tagstruct_getu32(t, &volume) < 0 ||
1238 pa_tagstruct_gets(t, &name) < 0 ||
1239 !pa_tagstruct_eof(t)) {
1240 protocol_error(c);
1241 return;
1244 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1245 CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
1246 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1248 if (sink_index != PA_INVALID_INDEX)
1249 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
1250 else
1251 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
1253 CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
1255 if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) {
1256 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1257 return;
1260 pa_pstream_send_simple_ack(c->pstream, tag);
1263 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) {
1264 struct connection *c = userdata;
1265 const char *name;
1266 assert(c && t);
1268 if (pa_tagstruct_gets(t, &name) < 0 ||
1269 !pa_tagstruct_eof(t)) {
1270 protocol_error(c);
1271 return;
1274 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1275 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1277 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
1278 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1279 return;
1282 pa_pstream_send_simple_ack(c->pstream, tag);
1285 static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
1286 assert(t && sink);
1287 pa_tagstruct_put(
1289 PA_TAG_U32, sink->index,
1290 PA_TAG_STRING, sink->name,
1291 PA_TAG_STRING, sink->description,
1292 PA_TAG_SAMPLE_SPEC, &sink->sample_spec,
1293 PA_TAG_CHANNEL_MAP, &sink->channel_map,
1294 PA_TAG_U32, sink->owner ? sink->owner->index : PA_INVALID_INDEX,
1295 PA_TAG_CVOLUME, pa_sink_get_volume(sink, PA_MIXER_HARDWARE),
1296 PA_TAG_BOOLEAN, pa_sink_get_mute(sink, PA_MIXER_HARDWARE),
1297 PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
1298 PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
1299 PA_TAG_USEC, pa_sink_get_latency(sink),
1300 PA_TAG_STRING, sink->driver,
1301 PA_TAG_U32,
1302 (sink->get_hw_volume ? PA_SINK_HW_VOLUME_CTRL : 0) |
1303 (sink->get_latency ? PA_SINK_LATENCY : 0) |
1304 (sink->is_hardware ? PA_SINK_HARDWARE : 0),
1305 PA_TAG_INVALID);
1308 static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
1309 assert(t && source);
1310 pa_tagstruct_put(
1312 PA_TAG_U32, source->index,
1313 PA_TAG_STRING, source->name,
1314 PA_TAG_STRING, source->description,
1315 PA_TAG_SAMPLE_SPEC, &source->sample_spec,
1316 PA_TAG_CHANNEL_MAP, &source->channel_map,
1317 PA_TAG_U32, source->owner ? source->owner->index : PA_INVALID_INDEX,
1318 PA_TAG_CVOLUME, pa_source_get_volume(source, PA_MIXER_HARDWARE),
1319 PA_TAG_BOOLEAN, pa_source_get_mute(source, PA_MIXER_HARDWARE),
1320 PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
1321 PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
1322 PA_TAG_USEC, pa_source_get_latency(source),
1323 PA_TAG_STRING, source->driver,
1324 PA_TAG_U32,
1325 (source->get_hw_volume ? PA_SOURCE_HW_VOLUME_CTRL : 0) |
1326 (source->get_latency ? PA_SOURCE_LATENCY : 0) |
1327 (source->is_hardware ? PA_SOURCE_HARDWARE : 0),
1328 PA_TAG_INVALID);
1331 static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
1332 assert(t && client);
1333 pa_tagstruct_putu32(t, client->index);
1334 pa_tagstruct_puts(t, client->name);
1335 pa_tagstruct_putu32(t, client->owner ? client->owner->index : PA_INVALID_INDEX);
1336 pa_tagstruct_puts(t, client->driver);
1339 static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
1340 assert(t && module);
1341 pa_tagstruct_putu32(t, module->index);
1342 pa_tagstruct_puts(t, module->name);
1343 pa_tagstruct_puts(t, module->argument);
1344 pa_tagstruct_putu32(t, module->n_used);
1345 pa_tagstruct_put_boolean(t, module->auto_unload);
1348 static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) {
1349 assert(t && s);
1350 pa_tagstruct_putu32(t, s->index);
1351 pa_tagstruct_puts(t, s->name);
1352 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
1353 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
1354 pa_tagstruct_putu32(t, s->sink->index);
1355 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1356 pa_tagstruct_put_channel_map(t, &s->channel_map);
1357 pa_tagstruct_put_cvolume(t, &s->volume);
1358 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
1359 pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
1360 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
1361 pa_tagstruct_puts(t, s->driver);
1364 static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
1365 assert(t && s);
1366 pa_tagstruct_putu32(t, s->index);
1367 pa_tagstruct_puts(t, s->name);
1368 pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
1369 pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
1370 pa_tagstruct_putu32(t, s->source->index);
1371 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1372 pa_tagstruct_put_channel_map(t, &s->channel_map);
1373 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s));
1374 pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
1375 pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
1376 pa_tagstruct_puts(t, s->driver);
1379 static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) {
1380 assert(t && e);
1381 pa_tagstruct_putu32(t, e->index);
1382 pa_tagstruct_puts(t, e->name);
1383 pa_tagstruct_put_cvolume(t, &e->volume);
1384 pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
1385 pa_tagstruct_put_sample_spec(t, &e->sample_spec);
1386 pa_tagstruct_put_channel_map(t, &e->channel_map);
1387 pa_tagstruct_putu32(t, e->memchunk.length);
1388 pa_tagstruct_put_boolean(t, e->lazy);
1389 pa_tagstruct_puts(t, e->filename);
1392 static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1393 struct connection *c = userdata;
1394 uint32_t idx;
1395 pa_sink *sink = NULL;
1396 pa_source *source = NULL;
1397 pa_client *client = NULL;
1398 pa_module *module = NULL;
1399 pa_sink_input *si = NULL;
1400 pa_source_output *so = NULL;
1401 pa_scache_entry *sce = NULL;
1402 const char *name;
1403 pa_tagstruct *reply;
1404 assert(c && t);
1406 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1407 (command != PA_COMMAND_GET_CLIENT_INFO &&
1408 command != PA_COMMAND_GET_MODULE_INFO &&
1409 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
1410 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
1411 pa_tagstruct_gets(t, &name) < 0) ||
1412 !pa_tagstruct_eof(t)) {
1413 protocol_error(c);
1414 return;
1417 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1418 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
1420 if (command == PA_COMMAND_GET_SINK_INFO) {
1421 if (idx != PA_INVALID_INDEX)
1422 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
1423 else
1424 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
1425 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
1426 if (idx != PA_INVALID_INDEX)
1427 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
1428 else
1429 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
1430 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
1431 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
1432 else if (command == PA_COMMAND_GET_MODULE_INFO)
1433 module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
1434 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
1435 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
1436 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
1437 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
1438 else {
1439 assert(command == PA_COMMAND_GET_SAMPLE_INFO);
1440 if (idx != PA_INVALID_INDEX)
1441 sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
1442 else
1443 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0);
1446 if (!sink && !source && !client && !module && !si && !so && !sce) {
1447 pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1448 return;
1451 reply = reply_new(tag);
1452 if (sink)
1453 sink_fill_tagstruct(reply, sink);
1454 else if (source)
1455 source_fill_tagstruct(reply, source);
1456 else if (client)
1457 client_fill_tagstruct(reply, client);
1458 else if (module)
1459 module_fill_tagstruct(reply, module);
1460 else if (si)
1461 sink_input_fill_tagstruct(reply, si);
1462 else if (so)
1463 source_output_fill_tagstruct(reply, so);
1464 else
1465 scache_fill_tagstruct(reply, sce);
1466 pa_pstream_send_tagstruct(c->pstream, reply);
1469 static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1470 struct connection *c = userdata;
1471 pa_idxset *i;
1472 uint32_t idx;
1473 void *p;
1474 pa_tagstruct *reply;
1475 assert(c && t);
1477 if (!pa_tagstruct_eof(t)) {
1478 protocol_error(c);
1479 return;
1482 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1484 reply = reply_new(tag);
1486 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1487 i = c->protocol->core->sinks;
1488 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1489 i = c->protocol->core->sources;
1490 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1491 i = c->protocol->core->clients;
1492 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1493 i = c->protocol->core->modules;
1494 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1495 i = c->protocol->core->sink_inputs;
1496 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1497 i = c->protocol->core->source_outputs;
1498 else {
1499 assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1500 i = c->protocol->core->scache;
1503 if (i) {
1504 for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
1505 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1506 sink_fill_tagstruct(reply, p);
1507 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1508 source_fill_tagstruct(reply, p);
1509 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1510 client_fill_tagstruct(reply, p);
1511 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1512 module_fill_tagstruct(reply, p);
1513 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1514 sink_input_fill_tagstruct(reply, p);
1515 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1516 source_output_fill_tagstruct(reply, p);
1517 else {
1518 assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1519 scache_fill_tagstruct(reply, p);
1524 pa_pstream_send_tagstruct(c->pstream, reply);
1527 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) {
1528 struct connection *c = userdata;
1529 pa_tagstruct *reply;
1530 char txt[256];
1531 const char *n;
1532 assert(c && t);
1534 if (!pa_tagstruct_eof(t)) {
1535 protocol_error(c);
1536 return;
1539 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1541 reply = reply_new(tag);
1542 pa_tagstruct_puts(reply, PACKAGE_NAME);
1543 pa_tagstruct_puts(reply, PACKAGE_VERSION);
1544 pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt)));
1545 pa_tagstruct_puts(reply, pa_get_fqdn(txt, sizeof(txt)));
1546 pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec);
1548 n = pa_namereg_get_default_sink_name(c->protocol->core);
1549 pa_tagstruct_puts(reply, n);
1550 n = pa_namereg_get_default_source_name(c->protocol->core);
1551 pa_tagstruct_puts(reply, n);
1553 pa_tagstruct_putu32(reply, c->protocol->core->cookie);
1555 pa_pstream_send_tagstruct(c->pstream, reply);
1558 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
1559 pa_tagstruct *t;
1560 struct connection *c = userdata;
1561 assert(c && core);
1563 t = pa_tagstruct_new(NULL, 0);
1564 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
1565 pa_tagstruct_putu32(t, (uint32_t) -1);
1566 pa_tagstruct_putu32(t, e);
1567 pa_tagstruct_putu32(t, idx);
1568 pa_pstream_send_tagstruct(c->pstream, t);
1571 static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1572 struct connection *c = userdata;
1573 pa_subscription_mask_t m;
1574 assert(c && t);
1576 if (pa_tagstruct_getu32(t, &m) < 0 ||
1577 !pa_tagstruct_eof(t)) {
1578 protocol_error(c);
1579 return;
1582 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1583 CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
1585 if (c->subscription)
1586 pa_subscription_free(c->subscription);
1588 if (m != 0) {
1589 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
1590 assert(c->subscription);
1591 } else
1592 c->subscription = NULL;
1594 pa_pstream_send_simple_ack(c->pstream, tag);
1597 static void command_set_volume(
1598 PA_GCC_UNUSED pa_pdispatch *pd,
1599 uint32_t command,
1600 uint32_t tag,
1601 pa_tagstruct *t,
1602 void *userdata) {
1604 struct connection *c = userdata;
1605 uint32_t idx;
1606 pa_cvolume volume;
1607 pa_sink *sink = NULL;
1608 pa_source *source = NULL;
1609 pa_sink_input *si = NULL;
1610 const char *name = NULL;
1611 assert(c && t);
1613 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1614 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
1615 (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
1616 pa_tagstruct_get_cvolume(t, &volume) ||
1617 !pa_tagstruct_eof(t)) {
1618 protocol_error(c);
1619 return;
1622 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1623 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
1624 CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
1626 if (command == PA_COMMAND_SET_SINK_VOLUME) {
1627 if (idx != PA_INVALID_INDEX)
1628 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
1629 else
1630 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
1631 } else if (command == PA_COMMAND_SET_SOURCE_VOLUME) {
1632 if (idx != (uint32_t) -1)
1633 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
1634 else
1635 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
1636 } else {
1637 assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME);
1638 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
1641 CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
1643 if (sink)
1644 pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume);
1645 else if (source)
1646 pa_source_set_volume(source, PA_MIXER_HARDWARE, &volume);
1647 else if (si)
1648 pa_sink_input_set_volume(si, &volume);
1650 pa_pstream_send_simple_ack(c->pstream, tag);
1653 static void command_set_mute(
1654 PA_GCC_UNUSED pa_pdispatch *pd,
1655 uint32_t command,
1656 uint32_t tag,
1657 pa_tagstruct *t,
1658 void *userdata) {
1660 struct connection *c = userdata;
1661 uint32_t idx;
1662 int mute;
1663 pa_sink *sink = NULL;
1664 pa_source *source = NULL;
1665 const char *name = NULL;
1666 assert(c && t);
1668 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1669 pa_tagstruct_gets(t, &name) < 0 ||
1670 pa_tagstruct_get_boolean(t, &mute) ||
1671 !pa_tagstruct_eof(t)) {
1672 protocol_error(c);
1673 return;
1676 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1677 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
1679 if (command == PA_COMMAND_SET_SINK_MUTE) {
1680 if (idx != PA_INVALID_INDEX)
1681 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
1682 else
1683 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
1684 } else {
1685 assert(command == PA_COMMAND_SET_SOURCE_MUTE);
1686 if (idx != (uint32_t) -1)
1687 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
1688 else
1689 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
1692 CHECK_VALIDITY(c->pstream, sink || source, tag, PA_ERR_NOENTITY);
1694 if (sink)
1695 pa_sink_set_mute(sink, PA_MIXER_HARDWARE, mute);
1696 else if (source)
1697 pa_source_set_mute(source, PA_MIXER_HARDWARE, mute);
1699 pa_pstream_send_simple_ack(c->pstream, tag);
1702 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) {
1703 struct connection *c = userdata;
1704 uint32_t idx;
1705 int b;
1706 struct playback_stream *s, *ssync;
1707 assert(c && t);
1709 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1710 pa_tagstruct_get_boolean(t, &b) < 0 ||
1711 !pa_tagstruct_eof(t)) {
1712 protocol_error(c);
1713 return;
1716 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1717 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
1718 s = pa_idxset_get_by_index(c->output_streams, idx);
1719 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1720 CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
1722 pa_sink_input_cork(s->sink_input, b);
1723 pa_memblockq_prebuf_force(s->memblockq);
1725 /* Do the same for all other members in the sync group */
1726 for (ssync = s->prev; ssync; ssync = ssync->prev) {
1727 pa_sink_input_cork(ssync->sink_input, b);
1728 pa_memblockq_prebuf_force(ssync->memblockq);
1731 for (ssync = s->next; ssync; ssync = ssync->next) {
1732 pa_sink_input_cork(ssync->sink_input, b);
1733 pa_memblockq_prebuf_force(ssync->memblockq);
1736 pa_pstream_send_simple_ack(c->pstream, tag);
1739 static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1740 struct connection *c = userdata;
1741 uint32_t idx;
1742 struct playback_stream *s, *ssync;
1743 assert(c && t);
1745 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1746 !pa_tagstruct_eof(t)) {
1747 protocol_error(c);
1748 return;
1751 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1752 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
1753 s = pa_idxset_get_by_index(c->output_streams, idx);
1754 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1755 CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
1757 pa_memblockq_flush(s->memblockq);
1758 s->underrun = 0;
1760 /* Do the same for all other members in the sync group */
1761 for (ssync = s->prev; ssync; ssync = ssync->prev) {
1762 pa_memblockq_flush(ssync->memblockq);
1763 ssync->underrun = 0;
1766 for (ssync = s->next; ssync; ssync = ssync->next) {
1767 pa_memblockq_flush(ssync->memblockq);
1768 ssync->underrun = 0;
1771 pa_pstream_send_simple_ack(c->pstream, tag);
1772 pa_sink_notify(s->sink_input->sink);
1773 request_bytes(s);
1775 for (ssync = s->prev; ssync; ssync = ssync->prev)
1776 request_bytes(ssync);
1778 for (ssync = s->next; ssync; ssync = ssync->next)
1779 request_bytes(ssync);
1782 static void command_trigger_or_prebuf_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1783 struct connection *c = userdata;
1784 uint32_t idx;
1785 struct playback_stream *s;
1786 assert(c && t);
1788 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1789 !pa_tagstruct_eof(t)) {
1790 protocol_error(c);
1791 return;
1794 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1795 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
1796 s = pa_idxset_get_by_index(c->output_streams, idx);
1797 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1798 CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
1800 switch (command) {
1801 case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
1802 pa_memblockq_prebuf_force(s->memblockq);
1803 break;
1805 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
1806 pa_memblockq_prebuf_disable(s->memblockq);
1807 break;
1809 default:
1810 abort();
1813 pa_sink_notify(s->sink_input->sink);
1814 pa_pstream_send_simple_ack(c->pstream, tag);
1815 request_bytes(s);
1818 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) {
1819 struct connection *c = userdata;
1820 uint32_t idx;
1821 struct record_stream *s;
1822 int b;
1823 assert(c && t);
1825 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1826 pa_tagstruct_get_boolean(t, &b) < 0 ||
1827 !pa_tagstruct_eof(t)) {
1828 protocol_error(c);
1829 return;
1832 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1833 s = pa_idxset_get_by_index(c->record_streams, idx);
1834 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1836 pa_source_output_cork(s->source_output, b);
1837 pa_memblockq_prebuf_force(s->memblockq);
1838 pa_pstream_send_simple_ack(c->pstream, tag);
1841 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) {
1842 struct connection *c = userdata;
1843 uint32_t idx;
1844 struct record_stream *s;
1845 assert(c && t);
1847 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1848 !pa_tagstruct_eof(t)) {
1849 protocol_error(c);
1850 return;
1853 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1854 s = pa_idxset_get_by_index(c->record_streams, idx);
1855 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1857 pa_memblockq_flush(s->memblockq);
1858 pa_pstream_send_simple_ack(c->pstream, tag);
1861 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) {
1862 struct connection *c = userdata;
1863 const char *s;
1864 assert(c && t);
1866 if (pa_tagstruct_gets(t, &s) < 0 ||
1867 !pa_tagstruct_eof(t)) {
1868 protocol_error(c);
1869 return;
1872 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1873 CHECK_VALIDITY(c->pstream, !s || (*s && pa_utf8_valid(s)), tag, PA_ERR_INVALID);
1875 pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK);
1876 pa_pstream_send_simple_ack(c->pstream, tag);
1879 static void command_set_stream_name(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1880 struct connection *c = userdata;
1881 uint32_t idx;
1882 const char *name;
1883 assert(c && t);
1885 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1886 pa_tagstruct_gets(t, &name) < 0 ||
1887 !pa_tagstruct_eof(t)) {
1888 protocol_error(c);
1889 return;
1892 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1893 CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
1895 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
1896 struct playback_stream *s;
1898 s = pa_idxset_get_by_index(c->output_streams, idx);
1899 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1900 CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
1902 pa_sink_input_set_name(s->sink_input, name);
1904 } else {
1905 struct record_stream *s;
1907 s = pa_idxset_get_by_index(c->record_streams, idx);
1908 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1910 pa_source_output_set_name(s->source_output, name);
1913 pa_pstream_send_simple_ack(c->pstream, tag);
1916 static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1917 struct connection *c = userdata;
1918 uint32_t idx;
1919 assert(c && t);
1921 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1922 !pa_tagstruct_eof(t)) {
1923 protocol_error(c);
1924 return;
1927 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1929 if (command == PA_COMMAND_KILL_CLIENT) {
1930 pa_client *client;
1932 client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
1933 CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
1934 pa_client_kill(client);
1936 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
1937 pa_sink_input *s;
1939 s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
1940 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1942 pa_sink_input_kill(s);
1943 } else {
1944 pa_source_output *s;
1946 assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
1948 s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
1949 CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
1951 pa_source_output_kill(s);
1954 pa_pstream_send_simple_ack(c->pstream, tag);
1957 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) {
1958 struct connection *c = userdata;
1959 pa_module *m;
1960 const char *name, *argument;
1961 pa_tagstruct *reply;
1962 assert(c && t);
1964 if (pa_tagstruct_gets(t, &name) < 0 ||
1965 pa_tagstruct_gets(t, &argument) < 0 ||
1966 !pa_tagstruct_eof(t)) {
1967 protocol_error(c);
1968 return;
1971 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1972 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
1973 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
1975 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
1976 pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
1977 return;
1980 reply = reply_new(tag);
1981 pa_tagstruct_putu32(reply, m->index);
1982 pa_pstream_send_tagstruct(c->pstream, reply);
1985 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) {
1986 struct connection *c = userdata;
1987 uint32_t idx;
1988 pa_module *m;
1989 assert(c && t);
1991 if (pa_tagstruct_getu32(t, &idx) < 0 ||
1992 !pa_tagstruct_eof(t)) {
1993 protocol_error(c);
1994 return;
1997 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1998 m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
1999 CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
2001 pa_module_unload_request(m);
2002 pa_pstream_send_simple_ack(c->pstream, tag);
2005 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) {
2006 struct connection *c = userdata;
2007 const char *name, *module, *argument;
2008 uint32_t type;
2009 uint32_t idx;
2010 pa_tagstruct *reply;
2011 assert(c && t);
2013 if (pa_tagstruct_gets(t, &name) < 0 ||
2014 pa_tagstruct_getu32(t, &type) < 0 ||
2015 pa_tagstruct_gets(t, &module) < 0 ||
2016 pa_tagstruct_gets(t, &argument) < 0 ||
2017 !pa_tagstruct_eof(t)) {
2018 protocol_error(c);
2019 return;
2022 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2023 CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
2024 CHECK_VALIDITY(c->pstream, type == 0 || type == 1, tag, PA_ERR_INVALID);
2025 CHECK_VALIDITY(c->pstream, module && *module && pa_utf8_valid(module), tag, PA_ERR_INVALID);
2026 CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
2028 if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &idx) < 0) {
2029 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2030 return;
2033 reply = reply_new(tag);
2034 pa_tagstruct_putu32(reply, idx);
2035 pa_pstream_send_tagstruct(c->pstream, reply);
2038 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) {
2039 struct connection *c = userdata;
2040 const char *name = NULL;
2041 uint32_t type, idx = PA_IDXSET_INVALID;
2042 int r;
2043 assert(c && t);
2045 if ((pa_tagstruct_getu32(t, &idx) < 0 &&
2046 (pa_tagstruct_gets(t, &name) < 0 ||
2047 pa_tagstruct_getu32(t, &type) < 0)) ||
2048 !pa_tagstruct_eof(t)) {
2049 protocol_error(c);
2050 return;
2053 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2054 CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID);
2055 CHECK_VALIDITY(c->pstream, !name || (*name && pa_utf8_valid(name) && (type == 0 || type == 1)), tag, PA_ERR_INVALID);
2057 if (name)
2058 r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
2059 else
2060 r = pa_autoload_remove_by_index(c->protocol->core, idx);
2062 CHECK_VALIDITY(c->pstream, r >= 0, tag, PA_ERR_NOENTITY);
2064 pa_pstream_send_simple_ack(c->pstream, tag);
2067 static void autoload_fill_tagstruct(pa_tagstruct *t, const pa_autoload_entry *e) {
2068 assert(t && e);
2070 pa_tagstruct_putu32(t, e->index);
2071 pa_tagstruct_puts(t, e->name);
2072 pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1);
2073 pa_tagstruct_puts(t, e->module);
2074 pa_tagstruct_puts(t, e->argument);
2077 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) {
2078 struct connection *c = userdata;
2079 const pa_autoload_entry *a = NULL;
2080 uint32_t type, idx;
2081 const char *name;
2082 pa_tagstruct *reply;
2083 assert(c && t);
2085 if ((pa_tagstruct_getu32(t, &idx) < 0 &&
2086 (pa_tagstruct_gets(t, &name) < 0 ||
2087 pa_tagstruct_getu32(t, &type) < 0)) ||
2088 !pa_tagstruct_eof(t)) {
2089 protocol_error(c);
2090 return;
2093 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2094 CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID);
2095 CHECK_VALIDITY(c->pstream, !name || (*name && (type == 0 || type == 1) && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2097 if (name)
2098 a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
2099 else
2100 a = pa_autoload_get_by_index(c->protocol->core, idx);
2102 CHECK_VALIDITY(c->pstream, a, tag, PA_ERR_NOENTITY);
2104 reply = reply_new(tag);
2105 autoload_fill_tagstruct(reply, a);
2106 pa_pstream_send_tagstruct(c->pstream, reply);
2109 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) {
2110 struct connection *c = userdata;
2111 pa_tagstruct *reply;
2112 assert(c && t);
2114 if (!pa_tagstruct_eof(t)) {
2115 protocol_error(c);
2116 return;
2119 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2121 reply = reply_new(tag);
2123 if (c->protocol->core->autoload_hashmap) {
2124 pa_autoload_entry *a;
2125 void *state = NULL;
2127 while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL)))
2128 autoload_fill_tagstruct(reply, a);
2131 pa_pstream_send_tagstruct(c->pstream, reply);
2134 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2135 struct connection *c = userdata;
2136 uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
2137 const char *name = NULL;
2139 assert(c);
2140 assert(t);
2142 if (pa_tagstruct_getu32(t, &idx) < 0 ||
2143 pa_tagstruct_getu32(t, &idx_device) < 0 ||
2144 pa_tagstruct_gets(t, &name) < 0 ||
2145 !pa_tagstruct_eof(t)) {
2146 protocol_error(c);
2147 return;
2150 CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2151 CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2152 CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
2154 if (command == PA_COMMAND_MOVE_SINK_INPUT) {
2155 pa_sink_input *si = NULL;
2156 pa_sink *sink = NULL;
2158 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
2160 if (idx_device != PA_INVALID_INDEX)
2161 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
2162 else
2163 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
2165 CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
2167 if (pa_sink_input_move_to(si, sink, 0) < 0) {
2168 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2169 return;
2171 } else {
2172 pa_source_output *so = NULL;
2173 pa_source *source;
2175 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
2177 if (idx_device != PA_INVALID_INDEX)
2178 source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
2179 else
2180 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
2182 CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
2184 if (pa_source_output_move_to(so, source) < 0) {
2185 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2186 return;
2190 pa_pstream_send_simple_ack(c->pstream, tag);
2194 /*** pstream callbacks ***/
2196 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
2197 struct connection *c = userdata;
2198 assert(p && packet && packet->data && c);
2200 if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
2201 pa_log(__FILE__": invalid packet.");
2202 connection_free(c);
2206 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) {
2207 struct connection *c = userdata;
2208 struct output_stream *stream;
2209 assert(p && chunk && userdata);
2211 if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) {
2212 pa_log(__FILE__": client sent block for invalid stream.");
2213 /* Ignoring */
2214 return;
2217 if (stream->type == PLAYBACK_STREAM) {
2218 struct playback_stream *ps = (struct playback_stream*) stream;
2219 if (chunk->length >= ps->requested_bytes)
2220 ps->requested_bytes = 0;
2221 else
2222 ps->requested_bytes -= chunk->length;
2224 pa_memblockq_seek(ps->memblockq, offset, seek);
2226 if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) {
2227 pa_tagstruct *t;
2229 pa_log_warn(__FILE__": failed to push data into queue");
2231 /* Pushing this block into the queue failed, so we simulate
2232 * it by skipping ahead */
2234 pa_memblockq_seek(ps->memblockq, chunk->length, PA_SEEK_RELATIVE);
2236 /* Notify the user */
2237 t = pa_tagstruct_new(NULL, 0);
2238 pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
2239 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
2240 pa_tagstruct_putu32(t, ps->index);
2241 pa_pstream_send_tagstruct(p, t);
2244 ps->underrun = 0;
2246 pa_sink_notify(ps->sink_input->sink);
2248 } else {
2249 struct upload_stream *u = (struct upload_stream*) stream;
2250 size_t l;
2251 assert(u->type == UPLOAD_STREAM);
2253 if (!u->memchunk.memblock) {
2254 if (u->length == chunk->length) {
2255 u->memchunk = *chunk;
2256 pa_memblock_ref(u->memchunk.memblock);
2257 u->length = 0;
2258 } else {
2259 u->memchunk.memblock = pa_memblock_new(u->length, c->protocol->core->memblock_stat);
2260 u->memchunk.index = u->memchunk.length = 0;
2264 assert(u->memchunk.memblock);
2266 l = u->length;
2267 if (l > chunk->length)
2268 l = chunk->length;
2270 if (l > 0) {
2271 memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length,
2272 (uint8_t*) chunk->memblock->data+chunk->index, l);
2273 u->memchunk.length += l;
2274 u->length -= l;
2279 static void pstream_die_callback(pa_pstream *p, void *userdata) {
2280 struct connection *c = userdata;
2281 assert(p && c);
2282 connection_free(c);
2284 /* pa_log(__FILE__": connection died.");*/
2288 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
2289 struct connection *c = userdata;
2290 assert(p && c);
2292 send_memblock(c);
2295 /*** client callbacks ***/
2297 static void client_kill_cb(pa_client *c) {
2298 assert(c && c->userdata);
2299 connection_free(c->userdata);
2302 /*** socket server callbacks ***/
2304 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
2305 struct connection *c = userdata;
2306 assert(m && tv && c && c->auth_timeout_event == e);
2308 if (!c->authorized)
2309 connection_free(c);
2312 static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, void *userdata) {
2313 pa_protocol_native *p = userdata;
2314 struct connection *c;
2315 char cname[256], pname[128];
2316 assert(io && p);
2318 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
2319 pa_log_warn(__FILE__": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
2320 pa_iochannel_free(io);
2321 return;
2324 c = pa_xmalloc(sizeof(struct connection));
2326 c->authorized = !!p->public;
2328 if (!c->authorized && p->auth_ip_acl && pa_ip_acl_check(p->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
2329 pa_log_info(__FILE__": Client authenticated by IP ACL.");
2330 c->authorized = 1;
2333 if (!c->authorized) {
2334 struct timeval tv;
2335 pa_gettimeofday(&tv);
2336 tv.tv_sec += AUTH_TIMEOUT;
2337 c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
2338 } else
2339 c->auth_timeout_event = NULL;
2341 c->version = 8;
2342 c->protocol = p;
2343 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
2344 snprintf(cname, sizeof(cname), "Native client (%s)", pname);
2345 assert(p->core);
2346 c->client = pa_client_new(p->core, __FILE__, cname);
2347 assert(c->client);
2348 c->client->kill = client_kill_cb;
2349 c->client->userdata = c;
2350 c->client->owner = p->module;
2352 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->memblock_stat);
2353 assert(c->pstream);
2355 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
2356 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
2357 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
2358 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
2360 c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
2361 assert(c->pdispatch);
2363 c->record_streams = pa_idxset_new(NULL, NULL);
2364 c->output_streams = pa_idxset_new(NULL, NULL);
2365 assert(c->record_streams && c->output_streams);
2367 c->rrobin_index = PA_IDXSET_INVALID;
2368 c->subscription = NULL;
2370 pa_idxset_put(p->connections, c, NULL);
2373 #ifdef HAVE_CREDS
2374 if (pa_iochannel_creds_supported(io))
2375 pa_iochannel_creds_enable(io);
2377 #endif
2380 /*** module entry points ***/
2382 static int load_key(pa_protocol_native*p, const char*fn) {
2383 assert(p);
2385 p->auth_cookie_in_property = 0;
2387 if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) {
2388 pa_log_info(__FILE__": using already loaded auth cookie.");
2389 pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
2390 p->auth_cookie_in_property = 1;
2391 return 0;
2394 if (!fn)
2395 fn = PA_NATIVE_COOKIE_FILE;
2397 if (pa_authkey_load_auto(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0)
2398 return -1;
2400 pa_log_info(__FILE__": loading cookie from disk.");
2402 if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0)
2403 p->auth_cookie_in_property = 1;
2405 return 0;
2408 static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_modargs *ma) {
2409 pa_protocol_native *p;
2410 int public = 0;
2411 const char *acl;
2413 assert(c);
2414 assert(ma);
2416 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &public) < 0) {
2417 pa_log(__FILE__": auth-anonymous= expects a boolean argument.");
2418 return NULL;
2421 p = pa_xnew(pa_protocol_native, 1);
2422 p->core = c;
2423 p->module = m;
2424 p->public = public;
2425 p->server = NULL;
2426 p->auth_ip_acl = NULL;
2428 #ifdef HAVE_CREDS
2430 int a = 1;
2431 if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) {
2432 pa_log(__FILE__": auth-group-enabled= expects a boolean argument.");
2433 return NULL;
2435 p->auth_group = a ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", c->is_system_instance ? PA_ACCESS_GROUP : NULL)) : NULL;
2437 if (p->auth_group)
2438 pa_log_info(__FILE__": Allowing access to group '%s'.", p->auth_group);
2440 #endif
2443 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
2445 if (!(p->auth_ip_acl = pa_ip_acl_new(acl))) {
2446 pa_log(__FILE__": Failed to parse IP ACL '%s'", acl);
2447 goto fail;
2451 if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
2452 goto fail;
2454 p->connections = pa_idxset_new(NULL, NULL);
2455 assert(p->connections);
2457 return p;
2459 fail:
2460 #ifdef HAVE_CREDS
2461 pa_xfree(p->auth_group);
2462 #endif
2463 if (p->auth_ip_acl)
2464 pa_ip_acl_free(p->auth_ip_acl);
2465 pa_xfree(p);
2466 return NULL;
2469 pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
2470 char t[256];
2471 pa_protocol_native *p;
2473 if (!(p = protocol_new_internal(core, m, ma)))
2474 return NULL;
2476 p->server = server;
2477 pa_socket_server_set_callback(p->server, on_connection, p);
2479 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
2480 pa_strlist *l;
2481 l = pa_property_get(core, PA_NATIVE_SERVER_PROPERTY_NAME);
2482 l = pa_strlist_prepend(l, t);
2483 pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
2486 return p;
2489 void pa_protocol_native_free(pa_protocol_native *p) {
2490 struct connection *c;
2491 assert(p);
2493 while ((c = pa_idxset_first(p->connections, NULL)))
2494 connection_free(c);
2495 pa_idxset_free(p->connections, NULL, NULL);
2497 if (p->server) {
2498 char t[256];
2500 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
2501 pa_strlist *l;
2502 l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
2503 l = pa_strlist_remove(l, t);
2505 if (l)
2506 pa_property_replace(p->core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
2507 else
2508 pa_property_remove(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
2511 pa_socket_server_unref(p->server);
2514 if (p->auth_cookie_in_property)
2515 pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
2517 if (p->auth_ip_acl)
2518 pa_ip_acl_free(p->auth_ip_acl);
2520 #ifdef HAVE_CREDS
2521 pa_xfree(p->auth_group);
2522 #endif
2523 pa_xfree(p);
2526 pa_protocol_native* pa_protocol_native_new_iochannel(pa_core*core, pa_iochannel *io, pa_module *m, pa_modargs *ma) {
2527 pa_protocol_native *p;
2529 if (!(p = protocol_new_internal(core, m, ma)))
2530 return NULL;
2532 on_connection(NULL, io, p);
2534 return p;