]> code.delx.au - pulseaudio/blob - polyp/protocol-native.c
remove auto-load-sample stuff
[pulseaudio] / polyp / protocol-native.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU 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.
10
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.
15
16 You should have received a copy of the GNU 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
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <assert.h>
29 #include <stdlib.h>
30
31 #include "protocol-native.h"
32 #include "native-common.h"
33 #include "packet.h"
34 #include "client.h"
35 #include "source-output.h"
36 #include "sink-input.h"
37 #include "pstream.h"
38 #include "tagstruct.h"
39 #include "pdispatch.h"
40 #include "pstream-util.h"
41 #include "authkey.h"
42 #include "namereg.h"
43 #include "scache.h"
44 #include "xmalloc.h"
45 #include "util.h"
46 #include "subscribe.h"
47 #include "log.h"
48
49 struct connection;
50 struct pa_protocol_native;
51
52 struct record_stream {
53 struct connection *connection;
54 uint32_t index;
55 struct pa_source_output *source_output;
56 struct pa_memblockq *memblockq;
57 size_t fragment_size;
58 };
59
60 struct playback_stream {
61 int type;
62 struct connection *connection;
63 uint32_t index;
64 struct pa_sink_input *sink_input;
65 struct pa_memblockq *memblockq;
66 size_t requested_bytes;
67 int drain_request;
68 uint32_t drain_tag;
69 };
70
71 struct upload_stream {
72 int type;
73 struct connection *connection;
74 uint32_t index;
75 struct pa_memchunk memchunk;
76 size_t length;
77 char *name;
78 struct pa_sample_spec sample_spec;
79 };
80
81 struct output_stream {
82 int type;
83 };
84
85 enum {
86 UPLOAD_STREAM,
87 PLAYBACK_STREAM
88 };
89
90 struct connection {
91 int authorized;
92 struct pa_protocol_native *protocol;
93 struct pa_client *client;
94 struct pa_pstream *pstream;
95 struct pa_pdispatch *pdispatch;
96 struct pa_idxset *record_streams, *output_streams;
97 uint32_t rrobin_index;
98 struct pa_subscription *subscription;
99 };
100
101 struct pa_protocol_native {
102 struct pa_module *module;
103 int public;
104 struct pa_core *core;
105 struct pa_socket_server *server;
106 struct pa_idxset *connections;
107 uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
108 };
109
110 static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk);
111 static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length);
112 static void sink_input_kill_cb(struct pa_sink_input *i);
113 static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i);
114
115 static void request_bytes(struct playback_stream*s);
116
117 static void source_output_kill_cb(struct pa_source_output *o);
118 static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk);
119
120 static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
121 static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
122 static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
123 static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
124 static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
125 static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
126 static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
127 static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
128 static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
129 static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
130 static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
131 static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
132 static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
133 static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
134 static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
135 static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
136 static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
137 static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
138 static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
139 static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
140 static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
141 static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
142
143 static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
144 [PA_COMMAND_ERROR] = { NULL },
145 [PA_COMMAND_TIMEOUT] = { NULL },
146 [PA_COMMAND_REPLY] = { NULL },
147 [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { command_create_playback_stream },
148 [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { command_delete_stream },
149 [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = { command_drain_playback_stream },
150 [PA_COMMAND_CREATE_RECORD_STREAM] = { command_create_record_stream },
151 [PA_COMMAND_DELETE_RECORD_STREAM] = { command_delete_stream },
152 [PA_COMMAND_AUTH] = { command_auth },
153 [PA_COMMAND_REQUEST] = { NULL },
154 [PA_COMMAND_EXIT] = { command_exit },
155 [PA_COMMAND_SET_NAME] = { command_set_name },
156 [PA_COMMAND_LOOKUP_SINK] = { command_lookup },
157 [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup },
158 [PA_COMMAND_STAT] = { command_stat },
159 [PA_COMMAND_GET_PLAYBACK_LATENCY] = { command_get_playback_latency },
160 [PA_COMMAND_CREATE_UPLOAD_STREAM] = { command_create_upload_stream },
161 [PA_COMMAND_DELETE_UPLOAD_STREAM] = { command_delete_stream },
162 [PA_COMMAND_FINISH_UPLOAD_STREAM] = { command_finish_upload_stream },
163 [PA_COMMAND_PLAY_SAMPLE] = { command_play_sample },
164 [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample },
165 [PA_COMMAND_GET_SINK_INFO] = { command_get_info },
166 [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info },
167 [PA_COMMAND_GET_CLIENT_INFO] = { command_get_info },
168 [PA_COMMAND_GET_MODULE_INFO] = { command_get_info },
169 [PA_COMMAND_GET_SINK_INPUT_INFO] = { command_get_info },
170 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = { command_get_info },
171 [PA_COMMAND_GET_SAMPLE_INFO] = { command_get_info },
172 [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list },
173 [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list },
174 [PA_COMMAND_GET_MODULE_INFO_LIST] = { command_get_info_list },
175 [PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list },
176 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = { command_get_info_list },
177 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = { command_get_info_list },
178 [PA_COMMAND_GET_SAMPLE_INFO_LIST] = { command_get_info_list },
179 [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info },
180 [PA_COMMAND_SUBSCRIBE] = { command_subscribe },
181 [PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume },
182 [PA_COMMAND_SET_SINK_INPUT_VOLUME] = { command_set_volume },
183 [PA_COMMAND_CORK_PLAYBACK_STREAM] = { command_cork_playback_stream },
184 [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream },
185 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = { command_flush_or_trigger_playback_stream },
186 [PA_COMMAND_SET_DEFAULT_SINK] = { command_set_default_sink_or_source },
187 [PA_COMMAND_SET_DEFAULT_SOURCE] = { command_set_default_sink_or_source },
188 };
189
190 /* structure management */
191
192 static struct upload_stream* upload_stream_new(struct connection *c, const struct pa_sample_spec *ss, const char *name, size_t length) {
193 struct upload_stream *s;
194 assert(c && ss && name && length);
195
196 s = pa_xmalloc(sizeof(struct upload_stream));
197 s->type = UPLOAD_STREAM;
198 s->connection = c;
199 s->sample_spec = *ss;
200 s->name = pa_xstrdup(name);
201
202 s->memchunk.memblock = NULL;
203 s->memchunk.index = 0;
204 s->memchunk.length = 0;
205
206 s->length = length;
207
208 pa_idxset_put(c->output_streams, s, &s->index);
209 return s;
210 }
211
212 static void upload_stream_free(struct upload_stream *o) {
213 assert(o && o->connection);
214
215 pa_idxset_remove_by_data(o->connection->output_streams, o, NULL);
216
217 pa_xfree(o->name);
218
219 if (o->memchunk.memblock)
220 pa_memblock_unref(o->memchunk.memblock);
221
222 pa_xfree(o);
223 }
224
225 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) {
226 struct record_stream *s;
227 struct pa_source_output *source_output;
228 size_t base;
229 assert(c && source && ss && name && maxlength);
230
231 if (!(source_output = pa_source_output_new(source, name, ss)))
232 return NULL;
233
234 s = pa_xmalloc(sizeof(struct record_stream));
235 s->connection = c;
236 s->source_output = source_output;
237 s->source_output->push = source_output_push_cb;
238 s->source_output->kill = source_output_kill_cb;
239 s->source_output->userdata = s;
240 s->source_output->owner = c->protocol->module;
241 s->source_output->client = c->client;
242
243 s->memblockq = pa_memblockq_new(maxlength, 0, base = pa_frame_size(ss), 0, 0, c->protocol->core->memblock_stat);
244 assert(s->memblockq);
245
246 s->fragment_size = (fragment_size/base)*base;
247 if (!s->fragment_size)
248 s->fragment_size = base;
249
250 pa_idxset_put(c->record_streams, s, &s->index);
251 return s;
252 }
253
254 static void record_stream_free(struct record_stream* r) {
255 assert(r && r->connection);
256
257 pa_idxset_remove_by_data(r->connection->record_streams, r, NULL);
258 pa_source_output_disconnect(r->source_output);
259 pa_source_output_unref(r->source_output);
260 pa_memblockq_free(r->memblockq);
261 pa_xfree(r);
262 }
263
264 static struct playback_stream* playback_stream_new(struct connection *c, struct pa_sink *sink, const struct pa_sample_spec *ss, const char *name,
265 size_t maxlength,
266 size_t tlength,
267 size_t prebuf,
268 size_t minreq) {
269 struct playback_stream *s;
270 struct pa_sink_input *sink_input;
271 assert(c && sink && ss && name && maxlength);
272
273 if (!(sink_input = pa_sink_input_new(sink, name, ss, 0)))
274 return NULL;
275
276 s = pa_xmalloc(sizeof(struct playback_stream));
277 s->type = PLAYBACK_STREAM;
278 s->connection = c;
279 s->sink_input = sink_input;
280
281 s->sink_input->peek = sink_input_peek_cb;
282 s->sink_input->drop = sink_input_drop_cb;
283 s->sink_input->kill = sink_input_kill_cb;
284 s->sink_input->get_latency = sink_input_get_latency_cb;
285 s->sink_input->userdata = s;
286 s->sink_input->owner = c->protocol->module;
287 s->sink_input->client = c->client;
288
289 s->memblockq = pa_memblockq_new(maxlength, tlength, pa_frame_size(ss), prebuf, minreq, c->protocol->core->memblock_stat);
290 assert(s->memblockq);
291
292 s->requested_bytes = 0;
293 s->drain_request = 0;
294
295 pa_idxset_put(c->output_streams, s, &s->index);
296 return s;
297 }
298
299 static void playback_stream_free(struct playback_stream* p) {
300 assert(p && p->connection);
301
302 if (p->drain_request)
303 pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERROR_NOENTITY);
304
305 pa_idxset_remove_by_data(p->connection->output_streams, p, NULL);
306 pa_sink_input_disconnect(p->sink_input);
307 pa_sink_input_unref(p->sink_input);
308 pa_memblockq_free(p->memblockq);
309 pa_xfree(p);
310 }
311
312 static void connection_free(struct connection *c) {
313 struct record_stream *r;
314 struct output_stream *o;
315 assert(c && c->protocol);
316
317 pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
318 while ((r = pa_idxset_first(c->record_streams, NULL)))
319 record_stream_free(r);
320 pa_idxset_free(c->record_streams, NULL, NULL);
321
322 while ((o = pa_idxset_first(c->output_streams, NULL)))
323 if (o->type == PLAYBACK_STREAM)
324 playback_stream_free((struct playback_stream*) o);
325 else
326 upload_stream_free((struct upload_stream*) o);
327 pa_idxset_free(c->output_streams, NULL, NULL);
328
329 pa_pdispatch_unref(c->pdispatch);
330 pa_pstream_close(c->pstream);
331 pa_pstream_unref(c->pstream);
332 pa_client_free(c->client);
333
334 if (c->subscription)
335 pa_subscription_free(c->subscription);
336
337 pa_xfree(c);
338 }
339
340 static void request_bytes(struct playback_stream *s) {
341 struct pa_tagstruct *t;
342 size_t l;
343 assert(s);
344
345 if (!(l = pa_memblockq_missing(s->memblockq)))
346 return;
347
348 if (l <= s->requested_bytes)
349 return;
350
351 l -= s->requested_bytes;
352
353 if (l < pa_memblockq_get_minreq(s->memblockq))
354 return;
355
356 s->requested_bytes += l;
357
358 t = pa_tagstruct_new(NULL, 0);
359 assert(t);
360 pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
361 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
362 pa_tagstruct_putu32(t, s->index);
363 pa_tagstruct_putu32(t, l);
364 pa_pstream_send_tagstruct(s->connection->pstream, t);
365
366 /* pa_log(__FILE__": Requesting %u bytes\n", l); */
367 }
368
369 static void send_memblock(struct connection *c) {
370 uint32_t start;
371 struct record_stream *r;
372
373 start = PA_IDXSET_INVALID;
374 for (;;) {
375 struct pa_memchunk chunk;
376
377 if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index)))
378 return;
379
380 if (start == PA_IDXSET_INVALID)
381 start = c->rrobin_index;
382 else if (start == c->rrobin_index)
383 return;
384
385 if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
386 struct pa_memchunk schunk = chunk;
387
388 if (schunk.length > r->fragment_size)
389 schunk.length = r->fragment_size;
390
391 pa_pstream_send_memblock(c->pstream, r->index, 0, &schunk);
392 pa_memblockq_drop(r->memblockq, &chunk, schunk.length);
393 pa_memblock_unref(schunk.memblock);
394
395 return;
396 }
397 }
398 }
399
400 static void send_playback_stream_killed(struct playback_stream *p) {
401 struct pa_tagstruct *t;
402 assert(p);
403
404 t = pa_tagstruct_new(NULL, 0);
405 assert(t);
406 pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
407 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
408 pa_tagstruct_putu32(t, p->index);
409 pa_pstream_send_tagstruct(p->connection->pstream, t);
410 }
411
412 static void send_record_stream_killed(struct record_stream *r) {
413 struct pa_tagstruct *t;
414 assert(r);
415
416 t = pa_tagstruct_new(NULL, 0);
417 assert(t);
418 pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
419 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
420 pa_tagstruct_putu32(t, r->index);
421 pa_pstream_send_tagstruct(r->connection->pstream, t);
422 }
423
424
425 /*** sinkinput callbacks ***/
426
427 static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk) {
428 struct playback_stream *s;
429 assert(i && i->userdata && chunk);
430 s = i->userdata;
431
432 if (pa_memblockq_peek(s->memblockq, chunk) < 0)
433 return -1;
434
435 return 0;
436 }
437
438 static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length) {
439 struct playback_stream *s;
440 assert(i && i->userdata && length);
441 s = i->userdata;
442
443 pa_memblockq_drop(s->memblockq, chunk, length);
444 request_bytes(s);
445
446 if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) {
447 pa_pstream_send_simple_ack(s->connection->pstream, s->drain_tag);
448 s->drain_request = 0;
449 }
450
451 /*pa_log(__FILE__": after_drop: %u\n", pa_memblockq_get_length(s->memblockq));*/
452 }
453
454 static void sink_input_kill_cb(struct pa_sink_input *i) {
455 assert(i && i->userdata);
456 send_playback_stream_killed((struct playback_stream *) i->userdata);
457 playback_stream_free((struct playback_stream *) i->userdata);
458 }
459
460 static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) {
461 struct playback_stream *s;
462 assert(i && i->userdata);
463 s = i->userdata;
464
465 /*pa_log(__FILE__": get_latency: %u\n", pa_memblockq_get_length(s->memblockq));*/
466
467 return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec);
468 }
469
470 /*** source_output callbacks ***/
471
472 static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk) {
473 struct record_stream *s;
474 assert(o && o->userdata && chunk);
475 s = o->userdata;
476
477 pa_memblockq_push_align(s->memblockq, chunk, 0);
478 if (!pa_pstream_is_pending(s->connection->pstream))
479 send_memblock(s->connection);
480 }
481
482 static void source_output_kill_cb(struct pa_source_output *o) {
483 assert(o && o->userdata);
484 send_record_stream_killed((struct record_stream *) o->userdata);
485 record_stream_free((struct record_stream *) o->userdata);
486 }
487
488 /*** pdispatch callbacks ***/
489
490 static void protocol_error(struct connection *c) {
491 pa_log(__FILE__": protocol error, kicking client\n");
492 connection_free(c);
493 }
494
495 static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
496 struct connection *c = userdata;
497 struct playback_stream *s;
498 size_t maxlength, tlength, prebuf, minreq;
499 uint32_t sink_index;
500 const char *name, *sink_name;
501 struct pa_sample_spec ss;
502 struct pa_tagstruct *reply;
503 struct pa_sink *sink;
504 assert(c && t && c->protocol && c->protocol->core);
505
506 if (pa_tagstruct_gets(t, &name) < 0 ||
507 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
508 pa_tagstruct_getu32(t, &sink_index) < 0 ||
509 pa_tagstruct_gets(t, &sink_name) < 0 ||
510 pa_tagstruct_getu32(t, &maxlength) < 0 ||
511 pa_tagstruct_getu32(t, &tlength) < 0 ||
512 pa_tagstruct_getu32(t, &prebuf) < 0 ||
513 pa_tagstruct_getu32(t, &minreq) < 0 ||
514 !pa_tagstruct_eof(t)) {
515 protocol_error(c);
516 return;
517 }
518
519 if (!c->authorized) {
520 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
521 return;
522 }
523
524 if (sink_index != (uint32_t) -1)
525 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
526 else
527 sink = pa_namereg_get(c->protocol->core, *sink_name ? sink_name : NULL, PA_NAMEREG_SINK, 1);
528
529 if (!sink) {
530 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
531 return;
532 }
533
534 if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, tlength, prebuf, minreq))) {
535 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
536 return;
537 }
538
539 reply = pa_tagstruct_new(NULL, 0);
540 assert(reply);
541 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
542 pa_tagstruct_putu32(reply, tag);
543 pa_tagstruct_putu32(reply, s->index);
544 assert(s->sink_input);
545 pa_tagstruct_putu32(reply, s->sink_input->index);
546 pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq));
547 pa_pstream_send_tagstruct(c->pstream, reply);
548 request_bytes(s);
549 }
550
551 static void command_delete_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
552 struct connection *c = userdata;
553 uint32_t channel;
554 assert(c && t);
555
556 if (pa_tagstruct_getu32(t, &channel) < 0 ||
557 !pa_tagstruct_eof(t)) {
558 protocol_error(c);
559 return;
560 }
561
562 if (!c->authorized) {
563 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
564 return;
565 }
566
567 if (command == PA_COMMAND_DELETE_PLAYBACK_STREAM) {
568 struct playback_stream *s;
569 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != PLAYBACK_STREAM)) {
570 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
571 return;
572 }
573
574 playback_stream_free(s);
575 } else if (command == PA_COMMAND_DELETE_RECORD_STREAM) {
576 struct record_stream *s;
577 if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
578 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
579 return;
580 }
581
582 record_stream_free(s);
583 } else {
584 struct upload_stream *s;
585 assert(command == PA_COMMAND_DELETE_UPLOAD_STREAM);
586 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) {
587 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
588 return;
589 }
590
591 upload_stream_free(s);
592 }
593
594 pa_pstream_send_simple_ack(c->pstream, tag);
595 }
596
597 static void command_create_record_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
598 struct connection *c = userdata;
599 struct record_stream *s;
600 size_t maxlength, fragment_size;
601 uint32_t source_index;
602 const char *name, *source_name;
603 struct pa_sample_spec ss;
604 struct pa_tagstruct *reply;
605 struct pa_source *source;
606 assert(c && t && c->protocol && c->protocol->core);
607
608 if (pa_tagstruct_gets(t, &name) < 0 ||
609 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
610 pa_tagstruct_getu32(t, &source_index) < 0 ||
611 pa_tagstruct_gets(t, &source_name) < 0 ||
612 pa_tagstruct_getu32(t, &maxlength) < 0 ||
613 pa_tagstruct_getu32(t, &fragment_size) < 0 ||
614 !pa_tagstruct_eof(t)) {
615 protocol_error(c);
616 return;
617 }
618
619 if (!c->authorized) {
620 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
621 return;
622 }
623
624 if (source_index != (uint32_t) -1)
625 source = pa_idxset_get_by_index(c->protocol->core->sources, source_index);
626 else
627 source = pa_namereg_get(c->protocol->core, *source_name ? source_name : NULL, PA_NAMEREG_SOURCE, 1);
628
629 if (!source) {
630 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
631 return;
632 }
633
634 if (!(s = record_stream_new(c, source, &ss, name, maxlength, fragment_size))) {
635 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
636 return;
637 }
638
639 reply = pa_tagstruct_new(NULL, 0);
640 assert(reply);
641 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
642 pa_tagstruct_putu32(reply, tag);
643 pa_tagstruct_putu32(reply, s->index);
644 assert(s->source_output);
645 pa_tagstruct_putu32(reply, s->source_output->index);
646 pa_pstream_send_tagstruct(c->pstream, reply);
647 }
648
649 static void command_exit(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
650 struct connection *c = userdata;
651 assert(c && t);
652
653 if (!pa_tagstruct_eof(t)) {
654 protocol_error(c);
655 return;
656 }
657
658 if (!c->authorized) {
659 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
660 return;
661 }
662
663 assert(c->protocol && c->protocol->core && c->protocol->core->mainloop);
664 c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0);
665 pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
666 return;
667 }
668
669 static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
670 struct connection *c = userdata;
671 const void*cookie;
672 assert(c && t);
673
674 if (pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
675 !pa_tagstruct_eof(t)) {
676 protocol_error(c);
677 return;
678 }
679
680 if (!c->authorized) {
681 if (memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) != 0) {
682 pa_log(__FILE__": Denied access to client with invalid authorization key.\n");
683 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
684 return;
685 }
686
687 c->authorized = 1;
688 }
689
690 pa_pstream_send_simple_ack(c->pstream, tag);
691 return;
692 }
693
694 static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
695 struct connection *c = userdata;
696 const char *name;
697 assert(c && t);
698
699 if (pa_tagstruct_gets(t, &name) < 0 ||
700 !pa_tagstruct_eof(t)) {
701 protocol_error(c);
702 return;
703 }
704
705 pa_client_rename(c->client, name);
706 pa_pstream_send_simple_ack(c->pstream, tag);
707 return;
708 }
709
710 static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
711 struct connection *c = userdata;
712 const char *name;
713 uint32_t index = PA_IDXSET_INVALID;
714 assert(c && t);
715
716 if (pa_tagstruct_gets(t, &name) < 0 ||
717 !pa_tagstruct_eof(t)) {
718 protocol_error(c);
719 return;
720 }
721
722 if (!c->authorized) {
723 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
724 return;
725 }
726
727 if (command == PA_COMMAND_LOOKUP_SINK) {
728 struct pa_sink *sink;
729 if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1)))
730 index = sink->index;
731 } else {
732 struct pa_source *source;
733 assert(command == PA_COMMAND_LOOKUP_SOURCE);
734 if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1)))
735 index = source->index;
736 }
737
738 if (index == PA_IDXSET_INVALID)
739 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
740 else {
741 struct pa_tagstruct *reply;
742 reply = pa_tagstruct_new(NULL, 0);
743 assert(reply);
744 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
745 pa_tagstruct_putu32(reply, tag);
746 pa_tagstruct_putu32(reply, index);
747 pa_pstream_send_tagstruct(c->pstream, reply);
748 }
749 }
750
751 static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
752 struct connection *c = userdata;
753 uint32_t index;
754 struct playback_stream *s;
755 assert(c && t);
756
757 if (pa_tagstruct_getu32(t, &index) < 0 ||
758 !pa_tagstruct_eof(t)) {
759 protocol_error(c);
760 return;
761 }
762
763 if (!c->authorized) {
764 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
765 return;
766 }
767
768 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
769 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
770 return;
771 }
772
773 s->drain_request = 0;
774
775 pa_memblockq_prebuf_disable(s->memblockq);
776
777 if (!pa_memblockq_is_readable(s->memblockq)) {
778 pa_pstream_send_simple_ack(c->pstream, tag);
779 } else {
780 s->drain_request = 1;
781 s->drain_tag = tag;
782
783 pa_sink_notify(s->sink_input->sink);
784 }
785 }
786
787 static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
788 struct connection *c = userdata;
789 struct pa_tagstruct *reply;
790 assert(c && t);
791
792 if (!pa_tagstruct_eof(t)) {
793 protocol_error(c);
794 return;
795 }
796
797 if (!c->authorized) {
798 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
799 return;
800 }
801
802 reply = pa_tagstruct_new(NULL, 0);
803 assert(reply);
804 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
805 pa_tagstruct_putu32(reply, tag);
806 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total);
807 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->total_size);
808 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated);
809 pa_tagstruct_putu32(reply, c->protocol->core->memblock_stat->allocated_size);
810 pa_tagstruct_putu32(reply, pa_scache_total_size(c->protocol->core));
811 pa_pstream_send_tagstruct(c->pstream, reply);
812 }
813
814 static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
815 struct connection *c = userdata;
816 struct pa_tagstruct *reply;
817 struct playback_stream *s;
818 struct timeval tv, now;
819 uint32_t index;
820 assert(c && t);
821
822 if (pa_tagstruct_getu32(t, &index) < 0 ||
823 pa_tagstruct_get_timeval(t, &tv) < 0 ||
824 !pa_tagstruct_eof(t)) {
825 protocol_error(c);
826 return;
827 }
828
829 if (!c->authorized) {
830 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
831 return;
832 }
833
834 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
835 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
836 return;
837 }
838
839 reply = pa_tagstruct_new(NULL, 0);
840 assert(reply);
841 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
842 pa_tagstruct_putu32(reply, tag);
843 pa_tagstruct_put_usec(reply, pa_sink_input_get_latency(s->sink_input));
844 pa_tagstruct_put_usec(reply, pa_sink_get_latency(s->sink_input->sink));
845 pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq));
846 pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
847 pa_tagstruct_put_timeval(reply, &tv);
848 gettimeofday(&now, NULL);
849 pa_tagstruct_put_timeval(reply, &now);
850 pa_pstream_send_tagstruct(c->pstream, reply);
851 }
852
853 static void command_create_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
854 struct connection *c = userdata;
855 struct upload_stream *s;
856 size_t length;
857 const char *name;
858 struct pa_sample_spec ss;
859 struct pa_tagstruct *reply;
860 assert(c && t && c->protocol && c->protocol->core);
861
862 if (pa_tagstruct_gets(t, &name) < 0 ||
863 pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
864 pa_tagstruct_getu32(t, &length) < 0 ||
865 !pa_tagstruct_eof(t)) {
866 protocol_error(c);
867 return;
868 }
869
870 if (!c->authorized) {
871 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
872 return;
873 }
874
875 if ((length % pa_frame_size(&ss)) != 0 || length <= 0 || !*name) {
876 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
877 return;
878 }
879
880 if (!(s = upload_stream_new(c, &ss, name, length))) {
881 pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
882 return;
883 }
884
885 reply = pa_tagstruct_new(NULL, 0);
886 assert(reply);
887 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
888 pa_tagstruct_putu32(reply, tag);
889 pa_tagstruct_putu32(reply, s->index);
890 pa_pstream_send_tagstruct(c->pstream, reply);
891
892 reply = pa_tagstruct_new(NULL, 0);
893 assert(reply);
894 pa_tagstruct_putu32(reply, PA_COMMAND_REQUEST);
895 pa_tagstruct_putu32(reply, (uint32_t) -1); /* tag */
896 pa_tagstruct_putu32(reply, s->index);
897 pa_tagstruct_putu32(reply, length);
898 pa_pstream_send_tagstruct(c->pstream, reply);
899 }
900
901 static void command_finish_upload_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
902 struct connection *c = userdata;
903 uint32_t channel;
904 struct upload_stream *s;
905 uint32_t index;
906 assert(c && t);
907
908 if (pa_tagstruct_getu32(t, &channel) < 0 ||
909 !pa_tagstruct_eof(t)) {
910 protocol_error(c);
911 return;
912 }
913
914 if (!c->authorized) {
915 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
916 return;
917 }
918
919 if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || (s->type != UPLOAD_STREAM)) {
920 pa_pstream_send_error(c->pstream, tag, PA_ERROR_EXIST);
921 return;
922 }
923
924 pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &index);
925 pa_pstream_send_simple_ack(c->pstream, tag);
926 upload_stream_free(s);
927 }
928
929 static void command_play_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
930 struct connection *c = userdata;
931 uint32_t sink_index, volume;
932 struct pa_sink *sink;
933 const char *name, *sink_name;
934 assert(c && t);
935
936 if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
937 pa_tagstruct_gets(t, &sink_name) < 0 ||
938 pa_tagstruct_getu32(t, &volume) < 0 ||
939 pa_tagstruct_gets(t, &name) < 0 ||
940 !pa_tagstruct_eof(t)) {
941 protocol_error(c);
942 return;
943 }
944
945 if (!c->authorized) {
946 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
947 return;
948 }
949
950 if (sink_index != (uint32_t) -1)
951 sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
952 else
953 sink = pa_namereg_get(c->protocol->core, *sink_name ? sink_name : NULL, PA_NAMEREG_SINK, 1);
954
955 if (!sink) {
956 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
957 return;
958 }
959
960 if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) {
961 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
962 return;
963 }
964
965 pa_pstream_send_simple_ack(c->pstream, tag);
966 }
967
968 static void command_remove_sample(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
969 struct connection *c = userdata;
970 const char *name;
971 assert(c && t);
972
973 if (pa_tagstruct_gets(t, &name) < 0 ||
974 !pa_tagstruct_eof(t)) {
975 protocol_error(c);
976 return;
977 }
978
979 if (!c->authorized) {
980 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
981 return;
982 }
983
984 if (pa_scache_remove_item(c->protocol->core, name) < 0) {
985 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
986 return;
987 }
988
989 pa_pstream_send_simple_ack(c->pstream, tag);
990 }
991
992 static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) {
993 assert(t && sink);
994 pa_tagstruct_putu32(t, sink->index);
995 pa_tagstruct_puts(t, sink->name);
996 pa_tagstruct_puts(t, sink->description ? sink->description : "");
997 pa_tagstruct_put_sample_spec(t, &sink->sample_spec);
998 pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1);
999 pa_tagstruct_putu32(t, sink->volume);
1000 pa_tagstruct_putu32(t, sink->monitor_source->index);
1001 pa_tagstruct_puts(t, sink->monitor_source->name);
1002 pa_tagstruct_put_usec(t, pa_sink_get_latency(sink));
1003 }
1004
1005 static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) {
1006 assert(t && source);
1007 pa_tagstruct_putu32(t, source->index);
1008 pa_tagstruct_puts(t, source->name);
1009 pa_tagstruct_puts(t, source->description ? source->description : "");
1010 pa_tagstruct_put_sample_spec(t, &source->sample_spec);
1011 pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1);
1012 pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1);
1013 pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : "");
1014 }
1015
1016 static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *client) {
1017 assert(t && client);
1018 pa_tagstruct_putu32(t, client->index);
1019 pa_tagstruct_puts(t, client->name);
1020 pa_tagstruct_puts(t, client->protocol_name);
1021 pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1);
1022 }
1023
1024 static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *module) {
1025 assert(t && module);
1026 pa_tagstruct_putu32(t, module->index);
1027 pa_tagstruct_puts(t, module->name);
1028 pa_tagstruct_puts(t, module->argument ? module->argument : "");
1029 pa_tagstruct_putu32(t, module->n_used);
1030 pa_tagstruct_put_boolean(t, module->auto_unload);
1031 }
1032
1033 static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_input *s) {
1034 assert(t && s);
1035 pa_tagstruct_putu32(t, s->index);
1036 pa_tagstruct_puts(t, s->name ? s->name : "");
1037 pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1);
1038 pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
1039 pa_tagstruct_putu32(t, s->sink->index);
1040 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1041 pa_tagstruct_putu32(t, s->volume);
1042 pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
1043 pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
1044 }
1045
1046 static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) {
1047 assert(t && s);
1048 pa_tagstruct_putu32(t, s->index);
1049 pa_tagstruct_puts(t, s->name ? s->name : "");
1050 pa_tagstruct_putu32(t, s->owner ? s->owner->index : (uint32_t) -1);
1051 pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
1052 pa_tagstruct_putu32(t, s->source->index);
1053 pa_tagstruct_put_sample_spec(t, &s->sample_spec);
1054 }
1055
1056 static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) {
1057 assert(t && e);
1058 pa_tagstruct_putu32(t, e->index);
1059 pa_tagstruct_puts(t, e->name);
1060 pa_tagstruct_putu32(t, e->volume);
1061 pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
1062 pa_tagstruct_put_sample_spec(t, &e->sample_spec);
1063 pa_tagstruct_putu32(t, e->memchunk.length);
1064 }
1065
1066 static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1067 struct connection *c = userdata;
1068 uint32_t index;
1069 struct pa_sink *sink = NULL;
1070 struct pa_source *source = NULL;
1071 struct pa_client *client = NULL;
1072 struct pa_module *module = NULL;
1073 struct pa_sink_input *si = NULL;
1074 struct pa_source_output *so = NULL;
1075 struct pa_scache_entry *sce = NULL;
1076 const char *name;
1077 struct pa_tagstruct *reply;
1078 assert(c && t);
1079
1080
1081 if (pa_tagstruct_getu32(t, &index) < 0 ||
1082 (command != PA_COMMAND_GET_CLIENT_INFO &&
1083 command != PA_COMMAND_GET_MODULE_INFO &&
1084 command != PA_COMMAND_GET_SINK_INPUT_INFO &&
1085 command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
1086 pa_tagstruct_gets(t, &name) < 0) ||
1087 !pa_tagstruct_eof(t)) {
1088 protocol_error(c);
1089 return;
1090 }
1091
1092 if (!c->authorized) {
1093 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1094 return;
1095 }
1096
1097 if (command == PA_COMMAND_GET_SINK_INFO) {
1098 if (index != (uint32_t) -1)
1099 sink = pa_idxset_get_by_index(c->protocol->core->sinks, index);
1100 else
1101 sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1);
1102 } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
1103 if (index != (uint32_t) -1)
1104 source = pa_idxset_get_by_index(c->protocol->core->sources, index);
1105 else
1106 source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1);
1107 } else if (command == PA_COMMAND_GET_CLIENT_INFO)
1108 client = pa_idxset_get_by_index(c->protocol->core->clients, index);
1109 else if (command == PA_COMMAND_GET_MODULE_INFO)
1110 module = pa_idxset_get_by_index(c->protocol->core->modules, index);
1111 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
1112 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index);
1113 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
1114 so = pa_idxset_get_by_index(c->protocol->core->source_outputs, index);
1115 else {
1116 assert(command == PA_COMMAND_GET_SAMPLE_INFO && name);
1117 if (index != (uint32_t) -1)
1118 sce = pa_idxset_get_by_index(c->protocol->core->scache, index);
1119 else
1120 sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0);
1121 }
1122
1123 if (!sink && !source && !client && !module && !si && !so && !sce) {
1124 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1125 return;
1126 }
1127
1128 reply = pa_tagstruct_new(NULL, 0);
1129 assert(reply);
1130 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1131 pa_tagstruct_putu32(reply, tag);
1132 if (sink)
1133 sink_fill_tagstruct(reply, sink);
1134 else if (source)
1135 source_fill_tagstruct(reply, source);
1136 else if (client)
1137 client_fill_tagstruct(reply, client);
1138 else if (module)
1139 module_fill_tagstruct(reply, module);
1140 else if (si)
1141 sink_input_fill_tagstruct(reply, si);
1142 else if (so)
1143 source_output_fill_tagstruct(reply, so);
1144 else
1145 scache_fill_tagstruct(reply, sce);
1146 pa_pstream_send_tagstruct(c->pstream, reply);
1147 }
1148
1149 static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1150 struct connection *c = userdata;
1151 struct pa_idxset *i;
1152 uint32_t index;
1153 void *p;
1154 struct pa_tagstruct *reply;
1155 assert(c && t);
1156
1157 if (!pa_tagstruct_eof(t)) {
1158 protocol_error(c);
1159 return;
1160 }
1161
1162 if (!c->authorized) {
1163 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1164 return;
1165 }
1166
1167 reply = pa_tagstruct_new(NULL, 0);
1168 assert(reply);
1169 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1170 pa_tagstruct_putu32(reply, tag);
1171
1172 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1173 i = c->protocol->core->sinks;
1174 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1175 i = c->protocol->core->sources;
1176 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1177 i = c->protocol->core->clients;
1178 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1179 i = c->protocol->core->modules;
1180 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1181 i = c->protocol->core->sink_inputs;
1182 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1183 i = c->protocol->core->source_outputs;
1184 else {
1185 assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1186 i = c->protocol->core->scache;
1187 }
1188
1189 if (i) {
1190 for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) {
1191 if (command == PA_COMMAND_GET_SINK_INFO_LIST)
1192 sink_fill_tagstruct(reply, p);
1193 else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
1194 source_fill_tagstruct(reply, p);
1195 else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
1196 client_fill_tagstruct(reply, p);
1197 else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
1198 module_fill_tagstruct(reply, p);
1199 else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
1200 sink_input_fill_tagstruct(reply, p);
1201 else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
1202 source_output_fill_tagstruct(reply, p);
1203 else {
1204 assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
1205 scache_fill_tagstruct(reply, p);
1206 }
1207 }
1208 }
1209
1210 pa_pstream_send_tagstruct(c->pstream, reply);
1211 }
1212
1213 static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1214 struct connection *c = userdata;
1215 struct pa_tagstruct *reply;
1216 char txt[256];
1217 const char *n;
1218 assert(c && t);
1219
1220 if (!pa_tagstruct_eof(t)) {
1221 protocol_error(c);
1222 return;
1223 }
1224
1225 if (!c->authorized) {
1226 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1227 return;
1228 }
1229
1230 reply = pa_tagstruct_new(NULL, 0);
1231 assert(reply);
1232 pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1233 pa_tagstruct_putu32(reply, tag);
1234 pa_tagstruct_puts(reply, PACKAGE_NAME);
1235 pa_tagstruct_puts(reply, PACKAGE_VERSION);
1236 pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt)));
1237 pa_tagstruct_puts(reply, pa_get_host_name(txt, sizeof(txt)));
1238 pa_tagstruct_put_sample_spec(reply, &c->protocol->core->default_sample_spec);
1239
1240 n = pa_namereg_get_default_sink_name(c->protocol->core);
1241 pa_tagstruct_puts(reply, n ? n : "");
1242 n = pa_namereg_get_default_source_name(c->protocol->core);
1243 pa_tagstruct_puts(reply, n ? n : "");
1244 pa_pstream_send_tagstruct(c->pstream, reply);
1245 }
1246
1247 static void subscription_cb(struct pa_core *core, enum pa_subscription_event_type e, uint32_t index, void *userdata) {
1248 struct pa_tagstruct *t;
1249 struct connection *c = userdata;
1250 assert(c && core);
1251
1252 t = pa_tagstruct_new(NULL, 0);
1253 assert(t);
1254 pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
1255 pa_tagstruct_putu32(t, (uint32_t) -1);
1256 pa_tagstruct_putu32(t, e);
1257 pa_tagstruct_putu32(t, index);
1258 pa_pstream_send_tagstruct(c->pstream, t);
1259 }
1260
1261 static void command_subscribe(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1262 struct connection *c = userdata;
1263 enum pa_subscription_mask m;
1264 assert(c && t);
1265
1266 if (pa_tagstruct_getu32(t, &m) < 0 ||
1267 !pa_tagstruct_eof(t)) {
1268 protocol_error(c);
1269 return;
1270 }
1271
1272 if (!c->authorized) {
1273 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1274 return;
1275 }
1276
1277 if (c->subscription)
1278 pa_subscription_free(c->subscription);
1279
1280 if (m != 0) {
1281 c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
1282 assert(c->subscription);
1283 } else
1284 c->subscription = NULL;
1285
1286 pa_pstream_send_simple_ack(c->pstream, tag);
1287 }
1288
1289 static void command_set_volume(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1290 struct connection *c = userdata;
1291 uint32_t index, volume;
1292 struct pa_sink *sink = NULL;
1293 struct pa_sink_input *si = NULL;
1294 const char *name = NULL;
1295 assert(c && t);
1296
1297 if (pa_tagstruct_getu32(t, &index) < 0 ||
1298 (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
1299 pa_tagstruct_getu32(t, &volume) ||
1300 !pa_tagstruct_eof(t)) {
1301 protocol_error(c);
1302 return;
1303 }
1304
1305 if (!c->authorized) {
1306 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1307 return;
1308 }
1309
1310 if (command == PA_COMMAND_SET_SINK_VOLUME) {
1311 if (index != (uint32_t) -1)
1312 sink = pa_idxset_get_by_index(c->protocol->core->sinks, index);
1313 else
1314 sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1);
1315 } else {
1316 assert(command == PA_COMMAND_SET_SINK_INPUT_VOLUME);
1317 si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index);
1318 }
1319
1320 if (!si && !sink) {
1321 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1322 return;
1323 }
1324
1325 if (sink)
1326 pa_sink_set_volume(sink, volume);
1327 else if (si)
1328 pa_sink_input_set_volume(si, volume);
1329
1330 pa_pstream_send_simple_ack(c->pstream, tag);
1331 }
1332
1333 static void command_cork_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1334 struct connection *c = userdata;
1335 uint32_t index;
1336 uint32_t b;
1337 struct playback_stream *s;
1338 assert(c && t);
1339
1340 if (pa_tagstruct_getu32(t, &index) < 0 ||
1341 pa_tagstruct_getu32(t, &b) < 0 ||
1342 !pa_tagstruct_eof(t)) {
1343 protocol_error(c);
1344 return;
1345 }
1346
1347 if (!c->authorized) {
1348 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1349 return;
1350 }
1351
1352 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
1353 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1354 return;
1355 }
1356
1357 pa_sink_input_cork(s->sink_input, b);
1358 pa_pstream_send_simple_ack(c->pstream, tag);
1359 }
1360
1361 static void command_flush_or_trigger_playback_stream(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1362 struct connection *c = userdata;
1363 uint32_t index;
1364 struct playback_stream *s;
1365 assert(c && t);
1366
1367 if (pa_tagstruct_getu32(t, &index) < 0 ||
1368 !pa_tagstruct_eof(t)) {
1369 protocol_error(c);
1370 return;
1371 }
1372
1373 if (!c->authorized) {
1374 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1375 return;
1376 }
1377
1378 if (!(s = pa_idxset_get_by_index(c->output_streams, index)) || s->type != PLAYBACK_STREAM) {
1379 pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
1380 return;
1381 }
1382
1383 if (command == PA_COMMAND_TRIGGER_PLAYBACK_STREAM)
1384 pa_memblockq_prebuf_disable(s->memblockq);
1385 else {
1386 assert(command == PA_COMMAND_FLUSH_PLAYBACK_STREAM);
1387 pa_memblockq_flush(s->memblockq);
1388 /*pa_log(__FILE__": flush: %u\n", pa_memblockq_get_length(s->memblockq));*/
1389 }
1390
1391 pa_sink_notify(s->sink_input->sink);
1392 pa_pstream_send_simple_ack(c->pstream, tag);
1393 request_bytes(s);
1394 }
1395
1396 static void command_set_default_sink_or_source(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
1397 struct connection *c = userdata;
1398 uint32_t index;
1399 const char *s;
1400 assert(c && t);
1401
1402 if (pa_tagstruct_getu32(t, &index) < 0 ||
1403 pa_tagstruct_gets(t, &s) < 0 ||
1404 !pa_tagstruct_eof(t)) {
1405 protocol_error(c);
1406 return;
1407 }
1408
1409 if (!c->authorized) {
1410 pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
1411 return;
1412 }
1413
1414 pa_namereg_set_default(c->protocol->core, s, command == PA_COMMAND_SET_DEFAULT_SOURCE ? PA_NAMEREG_SOURCE : PA_NAMEREG_SINK);
1415 pa_pstream_send_simple_ack(c->pstream, tag);
1416 }
1417
1418 /*** pstream callbacks ***/
1419
1420 static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
1421 struct connection *c = userdata;
1422 assert(p && packet && packet->data && c);
1423
1424 if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
1425 pa_log(__FILE__": invalid packet.\n");
1426 connection_free(c);
1427 }
1428 }
1429
1430 static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk, void *userdata) {
1431 struct connection *c = userdata;
1432 struct output_stream *stream;
1433 assert(p && chunk && userdata);
1434
1435 if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) {
1436 pa_log(__FILE__": client sent block for invalid stream.\n");
1437 connection_free(c);
1438 return;
1439 }
1440
1441 if (stream->type == PLAYBACK_STREAM) {
1442 struct playback_stream *p = (struct playback_stream*) stream;
1443 if (chunk->length >= p->requested_bytes)
1444 p->requested_bytes = 0;
1445 else
1446 p->requested_bytes -= chunk->length;
1447
1448 pa_memblockq_push_align(p->memblockq, chunk, delta);
1449 assert(p->sink_input);
1450 /*pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq));*/
1451
1452 pa_sink_notify(p->sink_input->sink);
1453 /* pa_log(__FILE__": Recieved %u bytes.\n", chunk->length); */
1454
1455 } else {
1456 struct upload_stream *u = (struct upload_stream*) stream;
1457 size_t l;
1458 assert(u->type == UPLOAD_STREAM);
1459
1460 if (!u->memchunk.memblock) {
1461 if (u->length == chunk->length) {
1462 u->memchunk = *chunk;
1463 pa_memblock_ref(u->memchunk.memblock);
1464 u->length = 0;
1465 } else {
1466 u->memchunk.memblock = pa_memblock_new(u->length, c->protocol->core->memblock_stat);
1467 u->memchunk.index = u->memchunk.length = 0;
1468 }
1469 }
1470
1471 assert(u->memchunk.memblock);
1472
1473 l = u->length;
1474 if (l > chunk->length)
1475 l = chunk->length;
1476
1477 if (l > 0) {
1478 memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length,
1479 (uint8_t*) chunk->memblock->data+chunk->index, l);
1480 u->memchunk.length += l;
1481 u->length -= l;
1482 }
1483 }
1484 }
1485
1486 static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
1487 struct connection *c = userdata;
1488 assert(p && c);
1489 connection_free(c);
1490
1491 /* pa_log(__FILE__": connection died.\n");*/
1492 }
1493
1494
1495 static void pstream_drain_callback(struct pa_pstream *p, void *userdata) {
1496 struct connection *c = userdata;
1497 assert(p && c);
1498
1499 send_memblock(c);
1500 }
1501
1502 /*** client callbacks ***/
1503
1504 static void client_kill_cb(struct pa_client *c) {
1505 assert(c && c->userdata);
1506 connection_free(c->userdata);
1507 }
1508
1509 /*** socket server callbacks ***/
1510
1511 static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, void *userdata) {
1512 struct pa_protocol_native *p = userdata;
1513 struct connection *c;
1514 assert(io && p);
1515
1516 c = pa_xmalloc(sizeof(struct connection));
1517
1518 c->authorized =!! p->public;
1519 c->protocol = p;
1520 assert(p->core);
1521 c->client = pa_client_new(p->core, "NATIVE", "Client");
1522 assert(c->client);
1523 c->client->kill = client_kill_cb;
1524 c->client->userdata = c;
1525 c->client->owner = p->module;
1526
1527 c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->memblock_stat);
1528 assert(c->pstream);
1529
1530 pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
1531 pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
1532 pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
1533 pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
1534
1535 c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
1536 assert(c->pdispatch);
1537
1538 c->record_streams = pa_idxset_new(NULL, NULL);
1539 c->output_streams = pa_idxset_new(NULL, NULL);
1540 assert(c->record_streams && c->output_streams);
1541
1542 c->rrobin_index = PA_IDXSET_INVALID;
1543 c->subscription = NULL;
1544
1545 pa_idxset_put(p->connections, c, NULL);
1546 }
1547
1548 /*** module entry points ***/
1549
1550 static struct pa_protocol_native* protocol_new_internal(struct pa_core *c, struct pa_module *m, struct pa_modargs *ma) {
1551 struct pa_protocol_native *p;
1552 int public = 0;
1553 assert(c && ma);
1554
1555 if (pa_modargs_get_value_boolean(ma, "public", &public) < 0) {
1556 pa_log(__FILE__": public= expects a boolean argument.\n");
1557 return NULL;
1558 }
1559
1560 p = pa_xmalloc(sizeof(struct pa_protocol_native));
1561
1562 if (pa_authkey_load_from_home(pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), p->auth_cookie, sizeof(p->auth_cookie)) < 0) {
1563 pa_xfree(p);
1564 return NULL;
1565 }
1566
1567 p->module = m;
1568 p->public = public;
1569 p->server = NULL;
1570 p->core = c;
1571 p->connections = pa_idxset_new(NULL, NULL);
1572 assert(p->connections);
1573
1574 return p;
1575 }
1576
1577 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) {
1578 struct pa_protocol_native *p;
1579
1580 if (!(p = protocol_new_internal(core, m, ma)))
1581 return NULL;
1582
1583 p->server = server;
1584 pa_socket_server_set_callback(p->server, on_connection, p);
1585
1586 return p;
1587 }
1588
1589 void pa_protocol_native_free(struct pa_protocol_native *p) {
1590 struct connection *c;
1591 assert(p);
1592
1593 while ((c = pa_idxset_first(p->connections, NULL)))
1594 connection_free(c);
1595 pa_idxset_free(p->connections, NULL, NULL);
1596
1597 if (p->server)
1598 pa_socket_server_unref(p->server);
1599
1600 pa_xfree(p);
1601 }
1602
1603 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) {
1604 struct pa_protocol_native *p;
1605
1606 if (!(p = protocol_new_internal(core, m, ma)))
1607 return NULL;
1608
1609 on_connection(NULL, io, p);
1610
1611 return p;
1612 }