4 This file is part of polypaudio.
6 polypaudio 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 polypaudio 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 polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include "protocol-native.h"
32 #include "native-common.h"
35 #include "source-output.h"
36 #include "sink-input.h"
38 #include "tagstruct.h"
39 #include "pdispatch.h"
40 #include "pstream-util.h"
46 #include "subscribe.h"
49 #include "authkey-prop.h"
54 struct pa_protocol_native;
56 struct record_stream {
57 struct connection *connection;
59 struct pa_source_output *source_output;
60 struct pa_memblockq *memblockq;
64 struct playback_stream {
66 struct connection *connection;
68 struct pa_sink_input *sink_input;
69 struct pa_memblockq *memblockq;
70 size_t requested_bytes;
75 struct upload_stream {
77 struct connection *connection;
79 struct pa_memchunk memchunk;
82 struct pa_sample_spec sample_spec;
85 struct output_stream {
96 struct pa_protocol_native *protocol;
97 struct pa_client *client;
98 struct pa_pstream *pstream;
99 struct pa_pdispatch *pdispatch;
100 struct pa_idxset *record_streams, *output_streams;
101 uint32_t rrobin_index;
102 struct pa_subscription *subscription;
105 struct pa_protocol_native {
106 struct pa_module *module;
108 struct pa_core *core;
109 struct pa_socket_server *server;
110 struct pa_idxset *connections;
111 uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
112 int auth_cookie_in_property;
115 static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk);
116 static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length);
117 static void sink_input_kill_cb(struct pa_sink_input *i);
118 static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i);
120 static void request_bytes(struct playback_stream*s);
122 static void source_output_kill_cb(struct pa_source_output *o);
123 static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk);
124 static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o);
126 static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
127 static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
128 static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
129 static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
130 static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
131 static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
132 static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
133 static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
134 static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
135 static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
136 static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
137 static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
138 static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
139 static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
140 static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
141 static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
142 static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
143 static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
144 static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
145 static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
146 static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
147 static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
148 static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
149 static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
150 static void command_kill(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
151 static void command_load_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
152 static void command_unload_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
153 static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
154 static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
155 static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
156 static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
157 static void command_cork_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
158 static void command_flush_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
160 static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
161 [PA_COMMAND_ERROR] = { NULL },
162 [PA_COMMAND_TIMEOUT] = { NULL },
163 [PA_COMMAND_REPLY] = { NULL },
164 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream },
165 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_stream },
166 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = { command_drain_playback_stream },
167 [PA_COMMAND_CREATE_RECORD_STREAM] = { command_create_record_stream },
168 [PA_COMMAND_DELETE_RECORD_STREAM] = { command_delete_stream },
169 [PA_COMMAND_AUTH] = { command_auth },
170 [PA_COMMAND_REQUEST] = { NULL },
171 [PA_COMMAND_EXIT] = { command_exit },
172 [PA_COMMAND_SET_CLIENT_NAME] = { command_set_client_name },
173 [PA_COMMAND_LOOKUP_SINK] = { command_lookup },
174 [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup },
175 [PA_COMMAND_STAT] = { command_stat },
176 [PA_COMMAND_GET_PLAYBACK_LATENCY] = { command_get_playback_latency },
177 [PA_COMMAND_GET_RECORD_LATENCY] = { command_get_record_latency },
178 [PA_COMMAND_CREATE_UPLOAD_STREAM] = { command_create_upload_stream },
179 [PA_COMMAND_DELETE_UPLOAD_STREAM] = { command_delete_stream },
180 [PA_COMMAND_FINISH_UPLOAD_STREAM] = { command_finish_upload_stream },
181 [PA_COMMAND_PLAY_SAMPLE] = { command_play_sample },
182 [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample },
183 [PA_COMMAND_GET_SINK_INFO] = { command_get_info },
184 [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info },
185 [PA_COMMAND_GET_CLIENT_INFO] = { command_get_info },
186 [PA_COMMAND_GET_MODULE_INFO] = { command_get_info },
187 [PA_COMMAND_GET_SINK_INPUT_INFO] = { command_get_info },
188 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = { command_get_info },
189 [PA_COMMAND_GET_SAMPLE_INFO] = { command_get_info },
190 [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list },
191 [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list },
192 [PA_COMMAND_GET_MODULE_INFO_LIST] = { command_get_info_list },
193 [PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list },
194 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = { command_get_info_list },
195 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = { command_get_info_list },
196 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = { command_get_info_list },
197 [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info },
198 [PA_COMMAND_SUBSCRIBE] = { command_subscribe },
200 [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume },
201 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = { command_set_volume },
203 [PA_COMMAND_CORK_PLAYBACK_STREAM] = { command_cork_playback_stream },
204 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream },
205 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream },
206 [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream },
208 [PA_COMMAND_CORK_RECORD_STREAM] = { command_cork_record_stream },
209 [PA_COMMAND_FLUSH_RECORD_STREAM] = { command_flush_record_stream },
211 [PA_COMMAND_SET_DEFAULT_SINK] = { command_set_default_sink_or_source },
212 [PA_COMMAND_SET_DEFAULT_SOURCE] = { command_set_default_sink_or_source },
213 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = { command_set_stream_name },
214 [PA_COMMAND_SET_RECORD_STREAM_NAME] = { command_set_stream_name },
215 [PA_COMMAND_KILL_CLIENT] = { command_kill },
216 [PA_COMMAND_KILL_SINK_INPUT] = { command_kill },
217 [PA_COMMAND_KILL_SOURCE_OUTPUT] = { command_kill },
218 [PA_COMMAND_LOAD_MODULE] = { command_load_module },
219 [PA_COMMAND_UNLOAD_MODULE] = { command_unload_module },
220 [PA_COMMAND_GET_AUTOLOAD_INFO] = { command_get_autoload_info },
221 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST] = { command_get_autoload_info_list },
222 [PA_COMMAND_ADD_AUTOLOAD] = { command_add_autoload },
223 [PA_COMMAND_REMOVE_AUTOLOAD] = { command_remove_autoload },
227 /* structure management */
229 static struct upload_stream* upload_stream_new(struct connection *c, const struct pa_sample_spec *ss, const char *name, size_t length) {
230 struct upload_stream *s;
231 assert(c && ss && name && length);
233 s = pa_xmalloc(sizeof(struct upload_stream));
234 s->type = UPLOAD_STREAM;
236 s->sample_spec = *ss;
237 s->name = pa_xstrdup(name);
239 s->memchunk.memblock = NULL;
240 s->memchunk.index = 0;
241 s->memchunk.length = 0;
245 pa_idxset_put(c->output_streams, s, &s->index);
249 static void upload_stream_free(struct upload_stream *o) {
250 assert(o && o->connection);
252 pa_idxset_remove_by_data(o->connection->output_streams, o, NULL);
256 if (o->memchunk.memblock)
257 pa_memblock_unref(o->memchunk.memblock);
262 static struct record_stream* record_stream_new(struct connection *c, struct pa_source *source, const struct pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) {
263 struct record_stream *s;
264 struct pa_source_output *source_output;
266 assert(c && source && ss && name && maxlength);
268 if (!(source_output = pa_source_output_new(source, name, ss, -1)))
271 s = pa_xmalloc(sizeof(struct record_stream));
273 s->source_output = source_output;
274 s->source_output->push = source_output_push_cb;
275 s->source_output->kill = source_output_kill_cb;
276 s->source_output->get_latency = source_output_get_latency_cb;
277 s->source_output->userdata = s;
278 s->source_output->owner = c->protocol->module;
279 s->source_output->client = c->client;
281 s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_frame_size(ss), 0, 0, c->protocol->core->memblock_stat);
282 assert(s->memblockq);
284 s->fragment_size = (fragment_size/base)*base;
285 if (!s->fragment_size)
286 s->fragment_size = base;
288 pa_idxset_put(c->record_streams, s, &s->index);
292 static void record_stream_free(struct record_stream* r) {
293 assert(r && r->connection);
295 pa_idxset_remove_by_data(r->connection->record_streams, r, NULL);
296 pa_source_output_disconnect(r->source_output);
297 pa_source_output_unref(r->source_output);
298 pa_memblockq_free(r->memblockq);
302 static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, const struct pa_sample_spec *ss, const char *name,
307 pa_volume_t volume) {
308 struct playback_stream *s;
309 struct pa_sink_input *sink_input;
310 assert(c && sink && ss && name && maxlength);
312 if (!(sink_input = pa_sink_input_new(sink, name, ss, 0, -1)))
315 s = pa_xmalloc(sizeof(struct playback_stream));
316 s->type = PLAYBACK_STREAM;
318 s->sink_input = sink_input;
320 s->sink_input->peek = sink_input_peek_cb;
321 s->sink_input->drop = sink_input_drop_cb;
322 s->sink_input->kill = sink_input_kill_cb;
323 s->sink_input->get_latency = sink_input_get_latency_cb;
324 s->sink_input->userdata = s;
325 s->sink_input->owner = c->protocol->module;
326 s->sink_input->client = c->client;
328 s->memblockq = pa_memblockq_new(maxlength, tlength, pa_frame_size(ss), prebuf, minreq, c->protocol->core->memblock_stat);
329 assert(s->memblockq);
331 s->requested_bytes = 0;
332 s->drain_request = 0;
334 s->sink_input->volume = volume;
336 pa_idxset_put(c->output_streams, s, &s->index);
340 static void playback_stream_free(struct playback_stream* p) {
341 assert(p && p->connection);
343 if (p->drain_request)
344 pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERROR_NOENTITY);
346 pa_idxset_remove_by_data(p->connection->output_streams, p, NULL);
347 pa_sink_input_disconnect(p->sink_input);
348 pa_sink_input_unref(p->sink_input);
349 pa_memblockq_free(p->memblockq);
353 static void connection_free(struct connection *c) {
354 struct record_stream *r;
355 struct output_stream *o;
356 assert(c && c->protocol);
358 pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
359 while ((r = pa_idxset_first(c->record_streams, NULL)))
360 record_stream_free(r);
361 pa_idxset_free(c->record_streams, NULL, NULL);
363 while ((o = pa_idxset_first(c->output_streams, NULL)))
364 if (o->type == PLAYBACK_STREAM)
365 playback_stream_free((struct playback_stream*) o);
367 upload_stream_free((struct upload_stream*) o);
368 pa_idxset_free(c->output_streams, NULL, NULL);
370 pa_pdispatch_unref(c->pdispatch);
371 pa_pstream_close(c->pstream);
372 pa_pstream_unref(c->pstream);
373 pa_client_free(c->client);
376 pa_subscription_free(c->subscription);
381 static void request_bytes(struct playback_stream *s) {
382 struct pa_tagstruct *t;
386 if (!(l = pa_memblockq_missing(s->memblockq)))
389 if (l <= s->requested_bytes)
392 l -= s->requested_bytes;
394 if (l < pa_memblockq_get_minreq(s->memblockq))
397 s->requested_bytes += l;
399 t = pa_tagstruct_new(NULL, 0);
401 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
402 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
403 pa_tagstruct_putu32(t, s->index);
404 pa_tagstruct_putu32(t, l);
405 pa_pstream_send_tagstruct(s->connection->pstream, t);
407 /* pa_log(__FILE__": Requesting %u bytes\n", l); */
410 static void send_memblock(struct connection *c) {
412 struct record_stream *r;
414 start = PA_IDXSET_INVALID;
416 struct pa_memchunk chunk;
418 if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index)))
421 if (start == PA_IDXSET_INVALID)
422 start = c->rrobin_index;
423 else if (start == c->rrobin_index)
426 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
427 struct pa_memchunk schunk = chunk;
429 if (schunk.length > r->fragment_size)
430 schunk.length = r->fragment_size;
432 pa_pstream_send_memblock(c->pstream, r->index, 0, &schunk);
433 pa_memblockq_drop(r->memblockq, &chunk, schunk.length);
434 pa_memblock_unref(schunk.memblock);
441 static void send_playback_stream_killed(struct playback_stream *p) {
442 struct pa_tagstruct *t;
445 t = pa_tagstruct_new(NULL, 0);
447 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
448 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
449 pa_tagstruct_putu32(t, p->index);
450 pa_pstream_send_tagstruct(p->connection->pstream, t);
453 static void send_record_stream_killed(struct record_stream *r) {
454 struct pa_tagstruct *t;
457 t = pa_tagstruct_new(NULL, 0);
459 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
460 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
461 pa_tagstruct_putu32(t, r->index);
462 pa_pstream_send_tagstruct(r->connection->pstream, t);
465 /*** sinkinput callbacks ***/
467 static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) {
468 struct playback_stream *s;
469 assert(i && i->userdata && chunk);
472 if (pa_memblockq_peek(s->memblockq, chunk) < 0)
478 static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) {
479 struct playback_stream *s;
480 assert(i && i->userdata && length);
483 pa_memblockq_drop(s->memblockq, chunk, length);
486 if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) {
487 pa_pstream_send_simple_ack(s->connection->pstream, s->drain_tag);
488 s->drain_request = 0;
491 /* pa_log(__FILE__": after_drop: %u\n", pa_memblockq_get_length(s->memblockq)); */
494 static void sink_input_kill_cb(struct pa_sink_input *i) {
495 assert(i && i->userdata);
496 send_playback_stream_killed((struct playback_stream *) i->userdata);
497 playback_stream_free((struct playback_stream *) i->userdata);
500 static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) {
501 struct playback_stream *s;
502 assert(i && i->userdata);
505 /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/
507 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec);
510 /*** source_output callbacks ***/
512 static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk) {
513 struct record_stream *s;
514 assert(o && o->userdata && chunk);
517 pa_memblockq_push_align(s->memblockq, chunk, 0);
518 if (!pa_pstream_is_pending(s->connection->pstream))
519 send_memblock(s->connection);
522 static void source_output_kill_cb(struct pa_source_output *o) {
523 assert(o && o->userdata);
524 send_record_stream_killed((struct record_stream *) o->userdata);
525 record_stream_free((struct record_stream *) o->userdata);
528 static pa_usec_t source_output_get_latency_cb(struct pa_source_output *o) {
529 struct record_stream *s;
530 assert(o && o->userdata);
533 /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/
535 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
538 /*** pdispatch callbacks ***/
540 static void protocol_error(struct connection *c) {
541 pa_log(__FILE__": protocol error, kicking client\n");
545 static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
546 struct connection *c = userdata;
547 struct playback_stream *s;
548 size_t maxlength, tlength, prebuf, minreq;
550 const char *name, *sink_name;
551 struct pa_sample_spec ss;
552 struct pa_tagstruct *reply;
553 struct pa_sink *sink;
556 assert(c && t && c->protocol && c->protocol->core);
558 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
559 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
560 pa_tagstruct_getu32(t, &sink_index) < 0 ||
561 pa_tagstruct_gets(t, &sink_name) < 0 ||
562 pa_tagstruct_getu32(t, &maxlength) < 0 ||
563 pa_tagstruct_get_boolean(t, &corked) < 0 ||
564 pa_tagstruct_getu32(t, &tlength) < 0 ||
565 pa_tagstruct_getu32(t, &prebuf) < 0 ||
566 pa_tagstruct_getu32(t, &minreq) < 0 ||
567 pa_tagstruct_getu32(t, &volume) < 0 ||
568 !pa_tagstruct_eof(t)) {
574 if (!c->authorized) {
575 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
579 if (sink_index != (uint32_t) -1)
580 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
582 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
585 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
589 if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, tlength, prebuf, minreq, volume))) {
590 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
594 pa_sink_input_cork(s->sink_input, corked);
596 reply = pa_tagstruct_new(NULL, 0);
598 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
599 pa_tagstruct_putu32(reply, tag);
600 pa_tagstruct_putu32(reply, s->index);
601 assert(s->sink_input);
602 pa_tagstruct_putu32(reply, s->sink_input->index);
603 pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq));
604 pa_pstream_send_tagstruct(c->pstream, reply);
608 static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
609 struct connection *c = userdata;
613 if (pa_tagstruct_getu32(t, &channel) < 0 ||
614 !pa_tagstruct_eof(t)) {
619 if (!c->authorized) {
620 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
624 if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) {
625 struct playback_stream *s;
626 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != PLAYBACK_STREAM)) {
627 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
631 playback_stream_free(s);
632 } else if (command == PA_COMMAND_DELETE_RECORD_STREAM) {
633 struct record_stream *s;
634 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
635 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
639 record_stream_free(s);
641 struct upload_stream *s;
642 assert(command == PA_COMMAND_DELETE_UPLOAD_STREAM);
643 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) {
644 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
648 upload_stream_free(s);
651 pa_pstream_send_simple_ack(c->pstream, tag);
654 static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
655 struct connection *c = userdata;
656 struct record_stream *s;
657 size_t maxlength, fragment_size;
658 uint32_t source_index;
659 const char *name, *source_name;
660 struct pa_sample_spec ss;
661 struct pa_tagstruct *reply;
662 struct pa_source *source;
664 assert(c && t && c->protocol && c->protocol->core);
666 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
667 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
668 pa_tagstruct_getu32(t, &source_index) < 0 ||
669 pa_tagstruct_gets(t, &source_name) < 0 ||
670 pa_tagstruct_getu32(t, &maxlength) < 0 ||
671 pa_tagstruct_get_boolean(t, &corked) < 0 ||
672 pa_tagstruct_getu32(t, &fragment_size) < 0 ||
673 !pa_tagstruct_eof(t)) {
678 if (!c->authorized) {
679 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
683 if (source_index != (uint32_t) -1)
684 source = pa_idxset_get_by_index(c->protocol->core->sources, source_index);
686 source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1);
689 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
693 if (!(s = record_stream_new(c, source, &ss, name, maxlength, fragment_size))) {
694 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
698 pa_source_output_cork(s->source_output, corked);
700 reply = pa_tagstruct_new(NULL, 0);
702 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
703 pa_tagstruct_putu32(reply, tag);
704 pa_tagstruct_putu32(reply, s->index);
705 assert(s->source_output);
706 pa_tagstruct_putu32(reply, s->source_output->index);
707 pa_pstream_send_tagstruct(c->pstream, reply);
710 static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
711 struct connection *c = userdata;
714 if (!pa_tagstruct_eof(t)) {
719 if (!c->authorized) {
720 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
724 assert(c->protocol && c->protocol->core && c->protocol->core->mainloop);
725 c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0);
726 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
730 static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
731 struct connection *c = userdata;
735 if (pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
736 !pa_tagstruct_eof(t)) {
741 if (!c->authorized) {
742 if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) {
743 pa_log(__FILE__": Denied access to client with invalid authorization key.\n");
744 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
751 pa_pstream_send_simple_ack(c->pstream, tag);
755 static void command_set_client_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
756 struct connection *c = userdata;
760 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
761 !pa_tagstruct_eof(t)) {
766 pa_client_set_name(c->client, name);
767 pa_pstream_send_simple_ack(c->pstream, tag);
771 static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
772 struct connection *c = userdata;
774 uint32_t index = PA_IDXSET_INVALID;
777 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
778 !pa_tagstruct_eof(t)) {
783 if (!c->authorized) {
784 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
788 if (command == PA_COMMAND_LOOKUP_SINK) {
789 struct pa_sink *sink;
790 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1)))
793 struct pa_source *source;
794 assert(command == PA_COMMAND_LOOKUP_SOURCE);
795 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1)))
796 index = source->index;
799 if (index == PA_IDXSET_INVALID)
800 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
802 struct pa_tagstruct *reply;
803 reply = pa_tagstruct_new(NULL, 0);
805 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
806 pa_tagstruct_putu32(reply, tag);
807 pa_tagstruct_putu32(reply, index);
808 pa_pstream_send_tagstruct(c->pstream, reply);
812 static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
813 struct connection *c = userdata;
815 struct playback_stream *s;
818 if (pa_tagstruct_getu32(t, &index) < 0 ||
819 !pa_tagstruct_eof(t)) {
824 if (!c->authorized) {
825 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
829 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
830 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
834 s->drain_request = 0;
836 pa_memblockq_prebuf_disable(s->memblockq);
838 if (!pa_memblockq_is_readable(s->memblockq)) {
839 /* pa_log("immediate drain: %u\n", pa_memblockq_get_length(s->memblockq)); */
840 pa_pstream_send_simple_ack(c->pstream, tag);
842 /* pa_log("slow drain triggered\n"); */
843 s->drain_request = 1;
846 pa_sink_notify(s->sink_input->sink);
850 static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
851 struct connection *c = userdata;
852 struct pa_tagstruct *reply;
855 if (!pa_tagstruct_eof(t)) {
860 if (!c->authorized) {
861 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
865 reply = pa_tagstruct_new(NULL, 0);
867 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
868 pa_tagstruct_putu32(reply, tag);
869 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total);
870 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total_size);
871 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated);
872 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated_size);
873 pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core));
874 pa_pstream_send_tagstruct(c->pstream, reply);
877 static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
878 struct connection *c = userdata;
879 struct pa_tagstruct *reply;
880 struct playback_stream *s;
881 struct timeval tv, now;
886 if (pa_tagstruct_getu32(t, &index) < 0 ||
887 pa_tagstruct_get_timeval(t, &tv) < 0 ||
888 pa_tagstruct_getu64(t, &counter) < 0 ||
889 !pa_tagstruct_eof(t)) {
894 if (!c->authorized) {
895 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
899 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
900 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
904 reply = pa_tagstruct_new(NULL, 0);
906 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
907 pa_tagstruct_putu32(reply, tag);
908 pa_tagstruct_put_usec(reply, pa_sink_input_get_latency(s->sink_input));
909 pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink));
910 pa_tagstruct_put_usec(reply, 0);
911 pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq));
912 pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
913 pa_tagstruct_put_timeval(reply, &tv);
914 gettimeofday(&now, NULL);
915 pa_tagstruct_put_timeval(reply, &now);
916 pa_tagstruct_putu64(reply, counter);
917 pa_pstream_send_tagstruct(c->pstream, reply);
920 static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
921 struct connection *c = userdata;
922 struct pa_tagstruct *reply;
923 struct record_stream *s;
924 struct timeval tv, now;
929 if (pa_tagstruct_getu32(t, &index) < 0 ||
930 pa_tagstruct_get_timeval(t, &tv) < 0 ||
931 pa_tagstruct_getu64(t, &counter) < 0 ||
932 !pa_tagstruct_eof(t)) {
937 if (!c->authorized) {
938 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
942 if (!(s = pa_idxset_get_by_index(c->record_streams, index))) {
943 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
947 reply = pa_tagstruct_new(NULL, 0);
949 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
950 pa_tagstruct_putu32(reply, tag);
951 pa_tagstruct_put_usec(reply, pa_source_output_get_latency(s->source_output));
952 pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
953 pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
954 pa_tagstruct_put_boolean(reply, 0);
955 pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
956 pa_tagstruct_put_timeval(reply, &tv);
957 gettimeofday(&now, NULL);
958 pa_tagstruct_put_timeval(reply, &now);
959 pa_tagstruct_putu64(reply, counter);
960 pa_pstream_send_tagstruct(c->pstream, reply);
964 static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
965 struct connection *c = userdata;
966 struct upload_stream *s;
969 struct pa_sample_spec ss;
970 struct pa_tagstruct *reply;
971 assert(c && t && c->protocol && c->protocol->core);
973 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
974 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
975 pa_tagstruct_getu32(t, &length) < 0 ||
976 !pa_tagstruct_eof(t)) {
981 if (!c->authorized) {
982 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
986 if ((length % pa_frame_size(&ss)) != 0 || length <= 0 || !*name) {
987 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
991 if (!(s = upload_stream_new(c, &ss, name, length))) {
992 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
996 reply = pa_tagstruct_new(NULL, 0);
998 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
999 pa_tagstruct_putu32(reply, tag);
1000 pa_tagstruct_putu32(reply, s->index);
1001 pa_tagstruct_putu32(reply, length);
1002 pa_pstream_send_tagstruct(c->pstream, reply);
1005 static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1006 struct connection *c = userdata;
1008 struct upload_stream *s;
1012 if (pa_tagstruct_getu32(t, &channel) < 0 ||
1013 !pa_tagstruct_eof(t)) {
1018 if (!c->authorized) {
1019 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1023 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) {
1024 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
1028 pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &index);
1029 pa_pstream_send_simple_ack(c->pstream, tag);
1030 upload_stream_free(s);
1033 static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1034 struct connection *c = userdata;
1035 uint32_t sink_index, volume;
1036 struct pa_sink *sink;
1037 const char *name, *sink_name;
1040 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
1041 pa_tagstruct_gets(t, &sink_name) < 0 ||
1042 pa_tagstruct_getu32(t, &volume) < 0 ||
1043 pa_tagstruct_gets(t, &name) < 0 || !name ||
1044 !pa_tagstruct_eof(t)) {
1049 if (!c->authorized) {
1050 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1054 if (sink_index != (uint32_t) -1)
1055 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
1057 sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
1060 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1064 if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) {
1065 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1069 pa_pstream_send_simple_ack(c->pstream, tag);
1072 static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1073 struct connection *c = userdata;
1077 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
1078 !pa_tagstruct_eof(t)) {
1083 if (!c->authorized) {
1084 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1088 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
1089 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1093 pa_pstream_send_simple_ack(c->pstream, tag);
1096 static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) {
1098 pa_tagstruct_putu32(t, sink->index);
1099 pa_tagstruct_puts(t, sink->name);
1100 pa_tagstruct_puts(t, sink->description);
1101 pa_tagstruct_put_sample_spec(t, &sink->sample_spec);
1102 pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1);
1103 pa_tagstruct_putu32(t, sink->volume);
1104 pa_tagstruct_putu32(t, sink->monitor_source->index);
1105 pa_tagstruct_puts(t, sink->monitor_source->name);
1106 pa_tagstruct_put_usec(t, pa_sink_get_latency(sink));
1109 static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) {
1110 assert(t && source);
1111 pa_tagstruct_putu32(t, source->index);
1112 pa_tagstruct_puts(t, source->name);
1113 pa_tagstruct_puts(t, source->description);
1114 pa_tagstruct_put_sample_spec(t, &source->sample_spec);
1115 pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1);
1116 pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1);
1117 pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : NULL);
1118 pa_tagstruct_put_usec(t, pa_source_get_latency(source));
1121 static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *client) {
1122 assert(t && client);
1123 pa_tagstruct_putu32(t, client->index);
1124 pa_tagstruct_puts(t, client->name);
1125 pa_tagstruct_puts(t, client->protocol_name);
1126 pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1);
1129 static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *module) {
1130 assert(t && module);
1131 pa_tagstruct_putu32(t, module->index);
1132 pa_tagstruct_puts(t, module->name);
1133 pa_tagstruct_puts(t, module->argument);
1134 pa_tagstruct_putu32(t, module->n_used);
1135 pa_tagstruct_put_boolean(t, module->auto_unload);
1138 static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_input *s) {
1140 pa_tagstruct_putu32(t, s->index);
1141 pa_tagstruct_puts(t, s->name);
1142 pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1);
1143 pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
1144 pa_tagstruct_putu32(t, s->sink->index);
1145 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1146 pa_tagstruct_putu32(t, s->volume);
1147 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
1148 pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
1151 static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) {
1153 pa_tagstruct_putu32(t, s->index);
1154 pa_tagstruct_puts(t, s->name);
1155 pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1);
1156 pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
1157 pa_tagstruct_putu32(t, s->source->index);
1158 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1159 pa_tagstruct_put_usec(t, pa_source_output_get_latency(s));
1160 pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
1163 static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) {
1165 pa_tagstruct_putu32(t, e->index);
1166 pa_tagstruct_puts(t, e->name);
1167 pa_tagstruct_putu32(t, e->volume);
1168 pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
1169 pa_tagstruct_put_sample_spec(t, &e->sample_spec);
1170 pa_tagstruct_putu32(t, e->memchunk.length);
1171 pa_tagstruct_put_boolean(t, e->lazy);
1172 pa_tagstruct_puts(t, e->filename);
1175 static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1176 struct connection *c = userdata;
1178 struct pa_sink *sink = NULL;
1179 struct pa_source *source = NULL;
1180 struct pa_client *client = NULL;
1181 struct pa_module *module = NULL;
1182 struct pa_sink_input *si = NULL;
1183 struct pa_source_output *so = NULL;
1184 struct pa_scache_entry *sce = NULL;
1186 struct pa_tagstruct *reply;
1190 if (pa_tagstruct_getu32(t, &index) < 0 ||
1191 (command != PA_COMMAND_GET_CLIENT_INFO &&
1192 command != PA_COMMAND_GET_MODULE_INFO &&
1193 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
1194 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
1195 pa_tagstruct_gets(t, &name) < 0) ||
1196 !pa_tagstruct_eof(t)) {
1201 if (!c->authorized) {
1202 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1206 if (command == PA_COMMAND_GET_SINK_INFO) {
1207 if (index != (uint32_t) -1)
1208 sink = pa_idxset_get_by_index(c->protocol->core->sinks, index);
1210 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
1211 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
1212 if (index != (uint32_t) -1)
1213 source = pa_idxset_get_by_index(c->protocol->core->sources, index);
1215 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
1216 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
1217 client = pa_idxset_get_by_index(c->protocol->core->clients, index);
1218 else if (command == PA_COMMAND_GET_MODULE_INFO)
1219 module = pa_idxset_get_by_index(c->protocol->core->modules, index);
1220 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
1221 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index);
1222 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
1223 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, index);
1225 assert(command == PA_COMMAND_GET_SAMPLE_INFO);
1226 if (index != (uint32_t) -1)
1227 sce = pa_idxset_get_by_index(c->protocol->core->scache, index);
1229 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0);
1232 if (!sink && !source && !client && !module && !si && !so && !sce) {
1233 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1237 reply = pa_tagstruct_new(NULL, 0);
1239 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1240 pa_tagstruct_putu32(reply, tag);
1242 sink_fill_tagstruct(reply, sink);
1244 source_fill_tagstruct(reply, source);
1246 client_fill_tagstruct(reply, client);
1248 module_fill_tagstruct(reply, module);
1250 sink_input_fill_tagstruct(reply, si);
1252 source_output_fill_tagstruct(reply, so);
1254 scache_fill_tagstruct(reply, sce);
1255 pa_pstream_send_tagstruct(c->pstream, reply);
1258 static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1259 struct connection *c = userdata;
1260 struct pa_idxset *i;
1263 struct pa_tagstruct *reply;
1266 if (!pa_tagstruct_eof(t)) {
1271 if (!c->authorized) {
1272 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1276 reply = pa_tagstruct_new(NULL, 0);
1278 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1279 pa_tagstruct_putu32(reply, tag);
1281 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1282 i = c->protocol->core->sinks;
1283 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1284 i = c->protocol->core->sources;
1285 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1286 i = c->protocol->core->clients;
1287 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1288 i = c->protocol->core->modules;
1289 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1290 i = c->protocol->core->sink_inputs;
1291 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1292 i = c->protocol->core->source_outputs;
1294 assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1295 i = c->protocol->core->scache;
1299 for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) {
1300 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1301 sink_fill_tagstruct(reply, p);
1302 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1303 source_fill_tagstruct(reply, p);
1304 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1305 client_fill_tagstruct(reply, p);
1306 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1307 module_fill_tagstruct(reply, p);
1308 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1309 sink_input_fill_tagstruct(reply, p);
1310 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1311 source_output_fill_tagstruct(reply, p);
1313 assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1314 scache_fill_tagstruct(reply, p);
1319 pa_pstream_send_tagstruct(c->pstream, reply);
1322 static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1323 struct connection *c = userdata;
1324 struct pa_tagstruct *reply;
1329 if (!pa_tagstruct_eof(t)) {
1334 if (!c->authorized) {
1335 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1339 reply = pa_tagstruct_new(NULL, 0);
1341 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1342 pa_tagstruct_putu32(reply, tag);
1343 pa_tagstruct_puts(reply, PACKAGE_NAME);
1344 pa_tagstruct_puts(reply, PACKAGE_VERSION);
1345 pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt)));
1346 pa_tagstruct_puts(reply, pa_get_fqdn(txt, sizeof(txt)));
1347 pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec);
1349 n = pa_namereg_get_default_sink_name(c->protocol->core);
1350 pa_tagstruct_puts(reply, n);
1351 n = pa_namereg_get_default_source_name(c->protocol->core);
1352 pa_tagstruct_puts(reply, n);
1353 pa_pstream_send_tagstruct(c->pstream, reply);
1356 static void subscription_cb(struct pa_core *core, enum pa_subscription_event_type e, uint32_t index, void *userdata) {
1357 struct pa_tagstruct *t;
1358 struct connection *c = userdata;
1361 t = pa_tagstruct_new(NULL, 0);
1363 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
1364 pa_tagstruct_putu32(t, (uint32_t) -1);
1365 pa_tagstruct_putu32(t, e);
1366 pa_tagstruct_putu32(t, index);
1367 pa_pstream_send_tagstruct(c->pstream, t);
1370 static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1371 struct connection *c = userdata;
1372 enum pa_subscription_mask m;
1375 if (pa_tagstruct_getu32(t, &m) < 0 ||
1376 !pa_tagstruct_eof(t)) {
1381 if (!c->authorized) {
1382 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1386 if (c->subscription)
1387 pa_subscription_free(c->subscription);
1390 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
1391 assert(c->subscription);
1393 c->subscription = NULL;
1395 pa_pstream_send_simple_ack(c->pstream, tag);
1398 static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1399 struct connection *c = userdata;
1400 uint32_t index, volume;
1401 struct pa_sink *sink = NULL;
1402 struct pa_sink_input *si = NULL;
1403 const char *name = NULL;
1406 if (pa_tagstruct_getu32(t, &index) < 0 ||
1407 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
1408 pa_tagstruct_getu32(t, &volume) ||
1409 !pa_tagstruct_eof(t)) {
1414 if (!c->authorized) {
1415 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1419 if (command == PA_COMMAND_SET_SINK_VOLUME) {
1420 if (index != (uint32_t) -1)
1421 sink = pa_idxset_get_by_index(c->protocol->core->sinks, index);
1423 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
1425 assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME);
1426 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index);
1430 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1435 pa_sink_set_volume(sink, volume);
1437 pa_sink_input_set_volume(si, volume);
1439 pa_pstream_send_simple_ack(c->pstream, tag);
1442 static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1443 struct connection *c = userdata;
1446 struct playback_stream *s;
1449 if (pa_tagstruct_getu32(t, &index) < 0 ||
1450 pa_tagstruct_get_boolean(t, &b) < 0 ||
1451 !pa_tagstruct_eof(t)) {
1456 if (!c->authorized) {
1457 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1461 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
1462 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1466 pa_sink_input_cork(s->sink_input, b);
1467 pa_pstream_send_simple_ack(c->pstream, tag);
1470 static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1471 struct connection *c = userdata;
1473 struct playback_stream *s;
1476 if (pa_tagstruct_getu32(t, &index) < 0 ||
1477 !pa_tagstruct_eof(t)) {
1482 if (!c->authorized) {
1483 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1487 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
1488 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1492 if (command == PA_COMMAND_PREBUF_PLAYBACK_STREAM)
1493 pa_memblockq_prebuf_reenable(s->memblockq);
1494 else if (command == PA_COMMAND_TRIGGER_PLAYBACK_STREAM)
1495 pa_memblockq_prebuf_disable(s->memblockq);
1497 assert(command == PA_COMMAND_FLUSH_PLAYBACK_STREAM);
1498 pa_memblockq_flush(s->memblockq);
1499 /*pa_log(__FILE__": flush: %u\n", pa_memblockq_get_length(s->memblockq));*/
1502 pa_sink_notify(s->sink_input->sink);
1503 pa_pstream_send_simple_ack(c->pstream, tag);
1507 static void command_cork_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1508 struct connection *c = userdata;
1510 struct record_stream *s;
1514 if (pa_tagstruct_getu32(t, &index) < 0 ||
1515 pa_tagstruct_get_boolean(t, &b) < 0 ||
1516 !pa_tagstruct_eof(t)) {
1521 if (!c->authorized) {
1522 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1526 if (!(s = pa_idxset_get_by_index(c->record_streams, index))) {
1527 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1531 pa_source_output_cork(s->source_output, b);
1532 pa_pstream_send_simple_ack(c->pstream, tag);
1535 static void command_flush_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1536 struct connection *c = userdata;
1538 struct record_stream *s;
1541 if (pa_tagstruct_getu32(t, &index) < 0 ||
1542 !pa_tagstruct_eof(t)) {
1547 if (!c->authorized) {
1548 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1552 if (!(s = pa_idxset_get_by_index(c->record_streams, index))) {
1553 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1557 pa_memblockq_flush(s->memblockq);
1558 pa_pstream_send_simple_ack(c->pstream, tag);
1561 static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1562 struct connection *c = userdata;
1567 if (pa_tagstruct_getu32(t, &index) < 0 ||
1568 pa_tagstruct_gets(t, &s) < 0 || !s ||
1569 !pa_tagstruct_eof(t)) {
1574 if (!c->authorized) {
1575 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1579 pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK);
1580 pa_pstream_send_simple_ack(c->pstream, tag);
1583 static void command_set_stream_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1584 struct connection *c = userdata;
1589 if (pa_tagstruct_getu32(t, &index) < 0 ||
1590 pa_tagstruct_gets(t, &name) < 0 || !name ||
1591 !pa_tagstruct_eof(t)) {
1596 if (!c->authorized) {
1597 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1601 if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
1602 struct playback_stream *s;
1604 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
1605 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1609 pa_sink_input_set_name(s->sink_input, name);
1612 struct record_stream *s;
1614 if (!(s = pa_idxset_get_by_index(c->record_streams, index))) {
1615 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1619 pa_source_output_set_name(s->source_output, name);
1622 pa_pstream_send_simple_ack(c->pstream, tag);
1625 static void command_kill(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1626 struct connection *c = userdata;
1630 if (pa_tagstruct_getu32(t, &index) < 0 ||
1631 !pa_tagstruct_eof(t)) {
1636 if (!c->authorized) {
1637 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1641 if (command == PA_COMMAND_KILL_CLIENT) {
1642 struct pa_client *client;
1644 if (!(client = pa_idxset_get_by_index(c->protocol->core->clients, index))) {
1645 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1649 pa_client_kill(client);
1650 } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
1651 struct pa_sink_input *s;
1653 if (!(s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index))) {
1654 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1658 pa_sink_input_kill(s);
1660 struct pa_source_output *s;
1662 assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
1664 if (!(s = pa_idxset_get_by_index(c->protocol->core->source_outputs, index))) {
1665 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1669 pa_source_output_kill(s);
1672 pa_pstream_send_simple_ack(c->pstream, tag);
1675 static void command_load_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1676 struct connection *c = userdata;
1677 struct pa_module *m;
1678 const char *name, *argument;
1679 struct pa_tagstruct *reply;
1682 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
1683 pa_tagstruct_gets(t, &argument) < 0 ||
1684 !pa_tagstruct_eof(t)) {
1689 if (!c->authorized) {
1690 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1694 if (!(m = pa_module_load(c->protocol->core, name, argument))) {
1695 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INITFAILED);
1699 reply = pa_tagstruct_new(NULL, 0);
1700 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1701 pa_tagstruct_putu32(reply, tag);
1702 pa_tagstruct_putu32(reply, m->index);
1703 pa_pstream_send_tagstruct(c->pstream, reply);
1706 static void command_unload_module(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1707 struct connection *c = userdata;
1709 struct pa_module *m;
1712 if (pa_tagstruct_getu32(t, &index) < 0 ||
1713 !pa_tagstruct_eof(t)) {
1718 if (!c->authorized) {
1719 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1723 if (!(m = pa_idxset_get_by_index(c->protocol->core->modules, index))) {
1724 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1728 pa_module_unload_request(m);
1729 pa_pstream_send_simple_ack(c->pstream, tag);
1732 static void command_add_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1733 struct connection *c = userdata;
1734 const char *name, *module, *argument;
1737 struct pa_tagstruct *reply;
1740 if (pa_tagstruct_gets(t, &name) < 0 || !name ||
1741 pa_tagstruct_getu32(t, &type) < 0 || type > 1 ||
1742 pa_tagstruct_gets(t, &module) < 0 || !module ||
1743 pa_tagstruct_gets(t, &argument) < 0 ||
1744 !pa_tagstruct_eof(t)) {
1749 if (!c->authorized) {
1750 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1754 if (pa_autoload_add(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, module, argument, &index) < 0) {
1755 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
1759 reply = pa_tagstruct_new(NULL, 0);
1760 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1761 pa_tagstruct_putu32(reply, tag);
1762 pa_tagstruct_putu32(reply, index);
1763 pa_pstream_send_tagstruct(c->pstream, reply);
1766 static void command_remove_autoload(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1767 struct connection *c = userdata;
1768 const char *name = NULL;
1769 uint32_t type, index = PA_IDXSET_INVALID;
1773 if ((pa_tagstruct_getu32(t, &index) < 0 &&
1774 (pa_tagstruct_gets(t, &name) < 0 ||
1775 pa_tagstruct_getu32(t, &type) < 0)) ||
1776 (!name && index == PA_IDXSET_INVALID) ||
1777 (name && type > 1) ||
1778 !pa_tagstruct_eof(t)) {
1783 if (!c->authorized) {
1784 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1789 r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
1791 r = pa_autoload_remove_by_index(c->protocol->core, index);
1794 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1798 pa_pstream_send_simple_ack(c->pstream, tag);
1801 static void autoload_fill_tagstruct(struct pa_tagstruct *t, const struct pa_autoload_entry *e) {
1804 pa_tagstruct_putu32(t, e->index);
1805 pa_tagstruct_puts(t, e->name);
1806 pa_tagstruct_putu32(t, e->type == PA_NAMEREG_SINK ? 0 : 1);
1807 pa_tagstruct_puts(t, e->module);
1808 pa_tagstruct_puts(t, e->argument);
1811 static void command_get_autoload_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1812 struct connection *c = userdata;
1813 const struct pa_autoload_entry *a = NULL;
1814 uint32_t type, index;
1816 struct pa_tagstruct *reply;
1819 if ((pa_tagstruct_getu32(t, &index) < 0 &&
1820 (pa_tagstruct_gets(t, &name) < 0 ||
1821 pa_tagstruct_getu32(t, &type) < 0)) ||
1822 (!name && index == PA_IDXSET_INVALID) ||
1823 (name && type > 1) ||
1824 !pa_tagstruct_eof(t)) {
1829 if (!c->authorized) {
1830 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1836 a = pa_autoload_get_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
1838 a = pa_autoload_get_by_index(c->protocol->core, index);
1841 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1845 reply = pa_tagstruct_new(NULL, 0);
1847 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1848 pa_tagstruct_putu32(reply, tag);
1849 autoload_fill_tagstruct(reply, a);
1850 pa_pstream_send_tagstruct(c->pstream, reply);
1853 static void command_get_autoload_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1854 struct connection *c = userdata;
1855 struct pa_tagstruct *reply;
1858 if (!pa_tagstruct_eof(t)) {
1863 if (!c->authorized) {
1864 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1868 reply = pa_tagstruct_new(NULL, 0);
1869 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1870 pa_tagstruct_putu32(reply, tag);
1872 if (c->protocol->core->autoload_hashmap) {
1873 struct pa_autoload_entry *a;
1876 while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL)))
1877 autoload_fill_tagstruct(reply, a);
1880 pa_pstream_send_tagstruct(c->pstream, reply);
1883 /*** pstream callbacks ***/
1885 static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
1886 struct connection *c = userdata;
1887 assert(p && packet && packet->data && c);
1889 if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
1890 pa_log(__FILE__": invalid packet.\n");
1895 static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata) {
1896 struct connection *c = userdata;
1897 struct output_stream *stream;
1898 assert(p && chunk && userdata);
1900 if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) {
1901 pa_log(__FILE__": client sent block for invalid stream.\n");
1906 if (stream->type == PLAYBACK_STREAM) {
1907 struct playback_stream *p = (struct playback_stream*) stream;
1908 if (chunk->length >= p->requested_bytes)
1909 p->requested_bytes = 0;
1911 p->requested_bytes -= chunk->length;
1913 pa_memblockq_push_align(p->memblockq, chunk, delta);
1914 assert(p->sink_input);
1915 /* pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq)); */
1917 pa_sink_notify(p->sink_input->sink);
1918 /* pa_log(__FILE__": Recieved %u bytes.\n", chunk->length); */
1921 struct upload_stream *u = (struct upload_stream*) stream;
1923 assert(u->type == UPLOAD_STREAM);
1925 if (!u->memchunk.memblock) {
1926 if (u->length == chunk->length) {
1927 u->memchunk = *chunk;
1928 pa_memblock_ref(u->memchunk.memblock);
1931 u->memchunk.memblock = pa_memblock_new(u->length, c->protocol->core->memblock_stat);
1932 u->memchunk.index = u->memchunk.length = 0;
1936 assert(u->memchunk.memblock);
1939 if (l > chunk->length)
1943 memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length,
1944 (uint8_t*) chunk->memblock->data+chunk->index, l);
1945 u->memchunk.length += l;
1951 static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
1952 struct connection *c = userdata;
1956 /* pa_log(__FILE__": connection died.\n");*/
1960 static void pstream_drain_callback(struct pa_pstream *p, void *userdata) {
1961 struct connection *c = userdata;
1967 /*** client callbacks ***/
1969 static void client_kill_cb(struct pa_client *c) {
1970 assert(c && c->userdata);
1971 connection_free(c->userdata);
1974 /*** socket server callbacks ***/
1976 static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) {
1977 struct pa_protocol_native *p = userdata;
1978 struct connection *c;
1981 c = pa_xmalloc(sizeof(struct connection));
1983 c->authorized =!! p->public;
1986 c->client = pa_client_new(p->core, "NATIVE", "Client");
1988 c->client->kill = client_kill_cb;
1989 c->client->userdata = c;
1990 c->client->owner = p->module;
1992 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->memblock_stat);
1995 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
1996 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
1997 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
1998 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
2000 c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
2001 assert(c->pdispatch);
2003 c->record_streams = pa_idxset_new(NULL, NULL);
2004 c->output_streams = pa_idxset_new(NULL, NULL);
2005 assert(c->record_streams && c->output_streams);
2007 c->rrobin_index = PA_IDXSET_INVALID;
2008 c->subscription = NULL;
2010 pa_idxset_put(p->connections, c, NULL);
2013 /*** module entry points ***/
2015 static int load_key(struct pa_protocol_native*p, const char*fn) {
2018 p->auth_cookie_in_property = 0;
2020 if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) {
2021 pa_log(__FILE__": using already loaded auth cookie.\n");
2022 pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
2023 p->auth_cookie_in_property = 1;
2028 fn = PA_NATIVE_COOKIE_FILE;
2030 if (pa_authkey_load_from_home(fn, p->auth_cookie, sizeof(p->auth_cookie)) < 0)
2033 pa_log(__FILE__": loading cookie from disk.\n");
2035 if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0)
2036 p->auth_cookie_in_property = 1;
2041 static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) {
2042 struct pa_protocol_native *p;
2046 if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) {
2047 pa_log(__FILE__": public= expects a boolean argument.\n");
2051 p = pa_xmalloc(sizeof(struct pa_protocol_native));
2057 if (load_key(p, pa_modargs_get_value(ma, "cookie", NULL)) < 0) {
2062 p->connections = pa_idxset_new(NULL, NULL);
2063 assert(p->connections);
2068 struct pa_protocol_native* pa_protocol_native_new(struct pa_core *core, struct pa_socket_server *server, struct pa_module *m, struct pa_modargs *ma) {
2070 struct pa_protocol_native *p;
2072 if (!(p = protocol_new_internal(core, m, ma)))
2076 pa_socket_server_set_callback(p->server, on_connection, p);
2078 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
2079 struct pa_strlist *l;
2080 l = pa_property_get(core, PA_NATIVE_SERVER_PROPERTY_NAME);
2081 l = pa_strlist_prepend(l, t);
2082 pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
2088 void pa_protocol_native_free(struct pa_protocol_native *p) {
2089 struct connection *c;
2092 while ((c = pa_idxset_first(p->connections, NULL)))
2094 pa_idxset_free(p->connections, NULL, NULL);
2099 if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
2100 struct pa_strlist *l;
2101 l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
2102 l = pa_strlist_remove(l, t);
2105 pa_property_replace(p->core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
2107 pa_property_remove(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
2110 pa_socket_server_unref(p->server);
2113 if (p->auth_cookie_in_property)
2114 pa_authkey_prop_unref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
2119 struct pa_protocol_native* pa_protocol_native_new_iochannel(struct pa_core*core, struct pa_iochannel *io, struct pa_module *m, struct pa_modargs *ma) {
2120 struct pa_protocol_native *p;
2122 if (!(p = protocol_new_internal(core, m, ma)))
2125 on_connection(NULL, io, p);