2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
32 #include <pulse/rtclock.h>
33 #include <pulse/sample.h>
34 #include <pulse/timeval.h>
35 #include <pulse/utf8.h>
36 #include <pulse/xmalloc.h>
37 #include <pulse/proplist.h>
39 #include <pulsecore/esound.h>
40 #include <pulsecore/memblock.h>
41 #include <pulsecore/client.h>
42 #include <pulsecore/sink-input.h>
43 #include <pulsecore/sink.h>
44 #include <pulsecore/source-output.h>
45 #include <pulsecore/source.h>
46 #include <pulsecore/core-scache.h>
47 #include <pulsecore/sample-util.h>
48 #include <pulsecore/namereg.h>
49 #include <pulsecore/log.h>
50 #include <pulsecore/core-util.h>
51 #include <pulsecore/core-error.h>
52 #include <pulsecore/ipacl.h>
53 #include <pulsecore/macro.h>
54 #include <pulsecore/thread-mq.h>
55 #include <pulsecore/shared.h>
56 #include <pulsecore/endianmacros.h>
58 #include "protocol-esound.h"
60 /* Don't accept more connection than this */
61 #define MAX_CONNECTIONS 64
63 /* Kick a client if it doesn't authenticate within this time */
64 #define AUTH_TIMEOUT (5*PA_USEC_PER_SEC)
66 #define DEFAULT_COOKIE_FILE ".esd_auth"
68 #define PLAYBACK_BUFFER_SECONDS (.25)
69 #define PLAYBACK_BUFFER_FRAGMENTS (10)
70 #define RECORD_BUFFER_SECONDS (5)
72 #define MAX_CACHE_SAMPLE_SIZE (2048000)
74 #define DEFAULT_SINK_LATENCY (150*PA_USEC_PER_MSEC)
75 #define DEFAULT_SOURCE_LATENCY (150*PA_USEC_PER_MSEC)
77 #define SCACHE_PREFIX "esound."
79 /* This is heavily based on esound's code */
81 typedef struct connection {
86 pa_esound_protocol *protocol;
87 pa_esound_options *options;
90 pa_bool_t authorized, swap_byte_order;
92 size_t write_data_alloc, write_data_index, write_data_length;
94 size_t read_data_alloc, read_data_length;
96 esd_client_state_t state;
97 pa_sink_input *sink_input;
98 pa_source_output *source_output;
99 pa_memblockq *input_memblockq, *output_memblockq;
100 pa_defer_event *defer_event;
105 pa_memblock *current_memblock;
106 size_t memblock_index;
112 pa_memchunk memchunk;
114 pa_sample_spec sample_spec;
117 pa_time_event *auth_timeout_event;
120 PA_DEFINE_PRIVATE_CLASS(connection, pa_msgobject);
121 #define CONNECTION(o) (connection_cast(o))
123 struct pa_esound_protocol {
127 pa_idxset *connections;
132 SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
133 SINK_INPUT_MESSAGE_DISABLE_PREBUF
137 CONNECTION_MESSAGE_REQUEST_DATA,
138 CONNECTION_MESSAGE_POST_DATA,
139 CONNECTION_MESSAGE_UNLINK_CONNECTION
142 typedef struct proto_handler {
144 int (*proc)(connection *c, esd_proto_t request, const void *data, size_t length);
145 const char *description;
146 } esd_proto_handler_info_t;
148 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
149 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
150 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
151 static void sink_input_kill_cb(pa_sink_input *i);
152 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
153 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
155 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
156 static void source_output_kill_cb(pa_source_output *o);
158 static int esd_proto_connect(connection *c, esd_proto_t request, const void *data, size_t length);
159 static int esd_proto_stream_play(connection *c, esd_proto_t request, const void *data, size_t length);
160 static int esd_proto_stream_record(connection *c, esd_proto_t request, const void *data, size_t length);
161 static int esd_proto_get_latency(connection *c, esd_proto_t request, const void *data, size_t length);
162 static int esd_proto_server_info(connection *c, esd_proto_t request, const void *data, size_t length);
163 static int esd_proto_all_info(connection *c, esd_proto_t request, const void *data, size_t length);
164 static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *data, size_t length);
165 static int esd_proto_sample_pan(connection *c, esd_proto_t request, const void *data, size_t length);
166 static int esd_proto_sample_cache(connection *c, esd_proto_t request, const void *data, size_t length);
167 static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length);
168 static int esd_proto_sample_get_id(connection *c, esd_proto_t request, const void *data, size_t length);
169 static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length);
170 static int esd_proto_standby_mode(connection *c, esd_proto_t request, const void *data, size_t length);
172 /* the big map of protocol handler info */
173 static struct proto_handler proto_map[ESD_PROTO_MAX] = {
174 { ESD_KEY_LEN + sizeof(int), esd_proto_connect, "connect" },
175 { ESD_KEY_LEN + sizeof(int), NULL, "lock" },
176 { ESD_KEY_LEN + sizeof(int), NULL, "unlock" },
178 { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_play, "stream play" },
179 { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream rec" },
180 { ESD_NAME_MAX + 2 * sizeof(int), esd_proto_stream_record, "stream mon" },
182 { ESD_NAME_MAX + 3 * sizeof(int), esd_proto_sample_cache, "sample cache" }, /* 6 */
183 { sizeof(int), esd_proto_sample_free_or_play, "sample free" },
184 { sizeof(int), esd_proto_sample_free_or_play, "sample play" }, /* 8 */
185 { sizeof(int), NULL, "sample loop" },
186 { sizeof(int), NULL, "sample stop" },
187 { (size_t) -1, NULL, "TODO: sample kill" },
189 { ESD_KEY_LEN + sizeof(int), esd_proto_standby_or_resume, "standby" },
190 { ESD_KEY_LEN + sizeof(int), esd_proto_standby_or_resume, "resume" }, /* 13 */
192 { ESD_NAME_MAX, esd_proto_sample_get_id, "sample getid" }, /* 14 */
193 { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" },
195 { sizeof(int), esd_proto_server_info, "server info" },
196 { sizeof(int), esd_proto_all_info, "all info" },
197 { (size_t) -1, NULL, "TODO: subscribe" },
198 { (size_t) -1, NULL, "TODO: unsubscribe" },
200 { 3 * sizeof(int), esd_proto_stream_pan, "stream pan"},
201 { 3 * sizeof(int), esd_proto_sample_pan, "sample pan" },
203 { sizeof(int), esd_proto_standby_mode, "standby mode" },
204 { 0, esd_proto_get_latency, "get latency" }
207 static void connection_unlink(connection *c) {
214 pa_esound_options_unref(c->options);
219 pa_sink_input_unlink(c->sink_input);
220 pa_sink_input_unref(c->sink_input);
221 c->sink_input = NULL;
224 if (c->source_output) {
225 pa_source_output_unlink(c->source_output);
226 pa_source_output_unref(c->source_output);
227 c->source_output = NULL;
231 pa_client_free(c->client);
235 if (c->state == ESD_STREAMING_DATA)
236 c->protocol->n_player--;
239 pa_iochannel_free(c->io);
243 if (c->defer_event) {
244 c->protocol->core->mainloop->defer_free(c->defer_event);
245 c->defer_event = NULL;
248 if (c->auth_timeout_event) {
249 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
250 c->auth_timeout_event = NULL;
253 pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
258 static void connection_free(pa_object *obj) {
259 connection *c = CONNECTION(obj);
262 if (c->input_memblockq)
263 pa_memblockq_free(c->input_memblockq);
264 if (c->output_memblockq)
265 pa_memblockq_free(c->output_memblockq);
267 if (c->playback.current_memblock)
268 pa_memblock_unref(c->playback.current_memblock);
270 pa_xfree(c->read_data);
271 pa_xfree(c->write_data);
273 if (c->scache.memchunk.memblock)
274 pa_memblock_unref(c->scache.memchunk.memblock);
275 pa_xfree(c->scache.name);
277 pa_xfree(c->original_name);
281 static void connection_write_prepare(connection *c, size_t length) {
285 t = c->write_data_length+length;
287 if (c->write_data_alloc < t)
288 c->write_data = pa_xrealloc(c->write_data, c->write_data_alloc = t);
290 pa_assert(c->write_data);
293 static void connection_write(connection *c, const void *data, size_t length) {
297 c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
299 connection_write_prepare(c, length);
301 pa_assert(c->write_data);
303 i = c->write_data_length;
304 c->write_data_length += length;
306 memcpy((uint8_t*) c->write_data + i, data, length);
309 static void format_esd2native(int format, pa_bool_t swap_bytes, pa_sample_spec *ss) {
312 ss->channels = (uint8_t) (((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1);
313 if ((format & ESD_MASK_BITS) == ESD_BITS16)
314 ss->format = swap_bytes ? PA_SAMPLE_S16RE : PA_SAMPLE_S16NE;
316 ss->format = PA_SAMPLE_U8;
319 static int format_native2esd(pa_sample_spec *ss) {
322 format = (ss->format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16;
323 format |= (ss->channels >= 2) ? ESD_STEREO : ESD_MONO;
328 #define CHECK_VALIDITY(expression, ...) do { \
329 if (PA_UNLIKELY(!(expression))) { \
330 pa_log_warn(__FILE__ ": " __VA_ARGS__); \
335 /*** esound commands ***/
337 static int esd_proto_connect(connection *c, esd_proto_t request, const void *data, size_t length) {
341 connection_assert_ref(c);
343 pa_assert(length == (ESD_KEY_LEN + sizeof(uint32_t)));
345 if (!c->authorized && c->options->auth_cookie) {
348 if ((key = pa_auth_cookie_read(c->options->auth_cookie, ESD_KEY_LEN)))
349 if (memcmp(data, key, ESD_KEY_LEN) == 0)
350 c->authorized = TRUE;
353 if (!c->authorized) {
354 pa_log("Kicked client with invalid authorization key.");
358 if (c->auth_timeout_event) {
359 c->protocol->core->mainloop->time_free(c->auth_timeout_event);
360 c->auth_timeout_event = NULL;
363 data = (const char*)data + ESD_KEY_LEN;
365 memcpy(&ekey, data, sizeof(uint32_t));
366 if (ekey == ESD_ENDIAN_KEY)
367 c->swap_byte_order = FALSE;
368 else if (ekey == ESD_SWAP_ENDIAN_KEY)
369 c->swap_byte_order = TRUE;
371 pa_log_warn("Client sent invalid endian key");
375 pa_proplist_sets(c->client->proplist, "esound.byte_order", c->swap_byte_order ? "reverse" : "native");
378 connection_write(c, &ok, sizeof(int));
382 static int esd_proto_stream_play(connection *c, esd_proto_t request, const void *data, size_t length) {
383 char name[ESD_NAME_MAX], *utf8_name;
384 int32_t format, rate;
387 pa_sink *sink = NULL;
388 pa_sink_input_new_data sdata;
391 connection_assert_ref(c);
393 pa_assert(length == (sizeof(int32_t)*2+ESD_NAME_MAX));
395 memcpy(&format, data, sizeof(int32_t));
396 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
397 data = (const char*) data + sizeof(int32_t);
399 memcpy(&rate, data, sizeof(int32_t));
400 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
401 data = (const char*) data + sizeof(int32_t);
403 ss.rate = (uint32_t) rate;
404 format_esd2native(format, c->swap_byte_order, &ss);
406 CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification");
408 if (c->options->default_sink) {
409 sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK);
410 CHECK_VALIDITY(sink, "No such sink: %s", pa_strnull(c->options->default_sink));
413 pa_strlcpy(name, data, sizeof(name));
415 utf8_name = pa_utf8_filter(name);
416 pa_client_set_name(c->client, utf8_name);
419 c->original_name = pa_xstrdup(name);
421 pa_assert(!c->sink_input && !c->input_memblockq);
423 pa_sink_input_new_data_init(&sdata);
424 sdata.driver = __FILE__;
425 sdata.module = c->options->module;
426 sdata.client = c->client;
428 pa_sink_input_new_data_set_sink(&sdata, sink, FALSE);
429 pa_sink_input_new_data_set_sample_spec(&sdata, &ss);
431 pa_sink_input_new(&c->sink_input, c->protocol->core, &sdata);
432 pa_sink_input_new_data_done(&sdata);
434 CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
436 l = (size_t) ((double) pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS);
437 pa_sink_input_get_silence(c->sink_input, &silence);
438 c->input_memblockq = pa_memblockq_new(
439 "esound protocol connection input_memblockq",
445 l/PLAYBACK_BUFFER_FRAGMENTS,
448 pa_memblock_unref(silence.memblock);
449 pa_iochannel_socket_set_rcvbuf(c->io, l);
451 c->sink_input->parent.process_msg = sink_input_process_msg;
452 c->sink_input->pop = sink_input_pop_cb;
453 c->sink_input->process_rewind = sink_input_process_rewind_cb;
454 c->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
455 c->sink_input->kill = sink_input_kill_cb;
456 c->sink_input->userdata = c;
458 pa_sink_input_set_requested_latency(c->sink_input, DEFAULT_SINK_LATENCY);
460 c->state = ESD_STREAMING_DATA;
462 c->protocol->n_player++;
464 pa_atomic_store(&c->playback.missing, (int) pa_memblockq_pop_missing(c->input_memblockq));
466 pa_sink_input_put(c->sink_input);
471 static int esd_proto_stream_record(connection *c, esd_proto_t request, const void *data, size_t length) {
472 char name[ESD_NAME_MAX], *utf8_name;
473 int32_t format, rate;
474 pa_source *source = NULL;
477 pa_source_output_new_data sdata;
479 connection_assert_ref(c);
481 pa_assert(length == (sizeof(int32_t)*2+ESD_NAME_MAX));
483 memcpy(&format, data, sizeof(int32_t));
484 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
485 data = (const char*) data + sizeof(int32_t);
487 memcpy(&rate, data, sizeof(int32_t));
488 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
489 data = (const char*) data + sizeof(int32_t);
491 ss.rate = (uint32_t) rate;
492 format_esd2native(format, c->swap_byte_order, &ss);
494 CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification.");
496 if (request == ESD_PROTO_STREAM_MON) {
499 sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK);
500 CHECK_VALIDITY(sink, "No such sink: %s", pa_strnull(c->options->default_sink));
502 source = sink->monitor_source;
503 CHECK_VALIDITY(source, "No such source.");
505 pa_assert(request == ESD_PROTO_STREAM_REC);
507 if (c->options->default_source) {
508 source = pa_namereg_get(c->protocol->core, c->options->default_source, PA_NAMEREG_SOURCE);
509 CHECK_VALIDITY(source, "No such source: %s", pa_strnull(c->options->default_source));
513 pa_strlcpy(name, data, sizeof(name));
515 utf8_name = pa_utf8_filter(name);
516 pa_client_set_name(c->client, utf8_name);
519 c->original_name = pa_xstrdup(name);
521 pa_assert(!c->output_memblockq && !c->source_output);
523 pa_source_output_new_data_init(&sdata);
524 sdata.driver = __FILE__;
525 sdata.module = c->options->module;
526 sdata.client = c->client;
528 pa_source_output_new_data_set_source(&sdata, source, FALSE);
529 pa_source_output_new_data_set_sample_spec(&sdata, &ss);
531 pa_source_output_new(&c->source_output, c->protocol->core, &sdata);
532 pa_source_output_new_data_done(&sdata);
534 CHECK_VALIDITY(c->source_output, "Failed to create source output.");
536 l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS);
537 c->output_memblockq = pa_memblockq_new(
538 "esound protocol connection output_memblockq",
547 pa_iochannel_socket_set_sndbuf(c->io, l);
549 c->source_output->push = source_output_push_cb;
550 c->source_output->kill = source_output_kill_cb;
551 c->source_output->get_latency = source_output_get_latency_cb;
552 c->source_output->userdata = c;
554 pa_source_output_set_requested_latency(c->source_output, DEFAULT_SOURCE_LATENCY);
556 c->state = ESD_STREAMING_DATA;
558 c->protocol->n_player++;
560 pa_source_output_put(c->source_output);
565 static int esd_proto_get_latency(connection *c, esd_proto_t request, const void *data, size_t length) {
569 connection_assert_ref(c);
571 pa_assert(length == 0);
573 if (!(sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK)))
576 double usec = (double) pa_sink_get_requested_latency(sink);
577 latency = (int) ((usec*44100)/1000000);
580 latency = PA_MAYBE_INT32_SWAP(c->swap_byte_order, latency);
581 connection_write(c, &latency, sizeof(int32_t));
586 static int esd_proto_server_info(connection *c, esd_proto_t request, const void *data, size_t length) {
587 int32_t rate = 44100, format = ESD_STEREO|ESD_BITS16;
591 connection_assert_ref(c);
593 pa_assert(length == sizeof(int32_t));
595 if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK))) {
596 rate = (int32_t) sink->sample_spec.rate;
597 format = format_native2esd(&sink->sample_spec);
600 connection_write_prepare(c, sizeof(int32_t) * 3);
603 connection_write(c, &response, sizeof(int32_t));
604 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
605 connection_write(c, &rate, sizeof(int32_t));
606 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
607 connection_write(c, &format, sizeof(int32_t));
612 static int esd_proto_all_info(connection *c, esd_proto_t request, const void *data, size_t length) {
615 uint32_t idx = PA_IDXSET_INVALID;
617 char terminator[sizeof(int32_t)*6+ESD_NAME_MAX];
619 connection_assert_ref(c);
621 pa_assert(length == sizeof(int32_t));
623 if (esd_proto_server_info(c, request, data, length) < 0)
626 k = sizeof(int32_t)*5+ESD_NAME_MAX;
627 s = sizeof(int32_t)*6+ESD_NAME_MAX;
628 nsamples = pa_idxset_size(c->protocol->core->scache);
629 t = s*(nsamples+1) + k*(c->protocol->n_player+1);
631 connection_write_prepare(c, t);
633 memset(terminator, 0, sizeof(terminator));
635 PA_IDXSET_FOREACH(conn, c->protocol->connections, idx) {
636 int32_t id, format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = ESD_VOLUME_BASE, rvolume = ESD_VOLUME_BASE;
637 char name[ESD_NAME_MAX];
639 if (conn->state != ESD_STREAMING_DATA)
642 pa_assert(t >= k*2+s);
644 if (conn->sink_input) {
646 pa_sink_input_get_volume(conn->sink_input, &volume, TRUE);
647 rate = (int32_t) conn->sink_input->sample_spec.rate;
648 lvolume = (int32_t) ((volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
649 rvolume = (int32_t) ((volume.values[volume.channels == 2 ? 1 : 0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
650 format = format_native2esd(&conn->sink_input->sample_spec);
654 id = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1));
655 connection_write(c, &id, sizeof(int32_t));
658 memset(name, 0, ESD_NAME_MAX); /* don't leak old data */
659 if (conn->original_name)
660 strncpy(name, conn->original_name, ESD_NAME_MAX);
661 else if (conn->client && pa_proplist_gets(conn->client->proplist, PA_PROP_APPLICATION_NAME))
662 strncpy(name, pa_proplist_gets(conn->client->proplist, PA_PROP_APPLICATION_NAME), ESD_NAME_MAX);
663 connection_write(c, name, ESD_NAME_MAX);
666 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
667 connection_write(c, &rate, sizeof(int32_t));
670 lvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, lvolume);
671 connection_write(c, &lvolume, sizeof(int32_t));
674 rvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rvolume);
675 connection_write(c, &rvolume, sizeof(int32_t));
678 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
679 connection_write(c, &format, sizeof(int32_t));
684 pa_assert(t == s*(nsamples+1)+k);
687 connection_write(c, terminator, k);
692 idx = PA_IDXSET_INVALID;
694 PA_IDXSET_FOREACH(ce, c->protocol->core->scache, idx) {
695 int32_t id, rate, lvolume, rvolume, format, len;
696 char name[ESD_NAME_MAX];
697 pa_channel_map stereo = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } };
703 if (ce->volume_is_set) {
705 pa_cvolume_remap(&volume, &ce->channel_map, &stereo);
707 pa_cvolume_reset(&volume, 2);
709 if (ce->memchunk.memblock)
710 ss = ce->sample_spec;
712 ss.format = PA_SAMPLE_S16NE;
718 id = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1));
719 connection_write(c, &id, sizeof(int32_t));
722 memset(name, 0, ESD_NAME_MAX); /* don't leak old data */
723 if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0)
724 strncpy(name, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX);
726 pa_snprintf(name, ESD_NAME_MAX, "native.%s", ce->name);
727 connection_write(c, name, ESD_NAME_MAX);
730 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ss.rate);
731 connection_write(c, &rate, sizeof(int32_t));
734 lvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ((volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM));
735 connection_write(c, &lvolume, sizeof(int32_t));
738 rvolume = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) ((volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM));
739 connection_write(c, &rvolume, sizeof(int32_t));
742 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ss));
743 connection_write(c, &format, sizeof(int32_t));
746 len = PA_MAYBE_INT32_SWAP(c->swap_byte_order, (int) ce->memchunk.length);
747 connection_write(c, &len, sizeof(int32_t));
755 connection_write(c, terminator, s);
760 static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *data, size_t length) {
762 uint32_t idx, lvolume, rvolume;
765 connection_assert_ref(c);
767 pa_assert(length == sizeof(int32_t)*3);
769 memcpy(&idx, data, sizeof(uint32_t));
770 idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
771 data = (const char*)data + sizeof(uint32_t);
773 memcpy(&lvolume, data, sizeof(uint32_t));
774 lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume);
775 data = (const char*)data + sizeof(uint32_t);
777 memcpy(&rvolume, data, sizeof(uint32_t));
778 rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
780 if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx)) && conn->sink_input) {
782 volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
783 volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
784 volume.channels = conn->sink_input->sample_spec.channels;
786 pa_sink_input_set_volume(conn->sink_input, &volume, TRUE, TRUE);
791 connection_write(c, &ok, sizeof(int32_t));
796 static int esd_proto_sample_pan(connection *c, esd_proto_t request, const void *data, size_t length) {
798 uint32_t idx, lvolume, rvolume;
802 connection_assert_ref(c);
804 pa_assert(length == sizeof(int32_t)*3);
806 memcpy(&idx, data, sizeof(uint32_t));
807 idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
808 data = (const char*)data + sizeof(uint32_t);
810 memcpy(&lvolume, data, sizeof(uint32_t));
811 lvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, lvolume);
812 data = (const char*)data + sizeof(uint32_t);
814 memcpy(&rvolume, data, sizeof(uint32_t));
815 rvolume = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
817 volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
818 volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
821 if ((ce = pa_idxset_get_by_index(c->protocol->core->scache, idx))) {
822 pa_channel_map stereo = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } };
824 pa_cvolume_remap(&volume, &stereo, &ce->channel_map);
826 ce->volume_is_set = TRUE;
830 connection_write(c, &ok, sizeof(int32_t));
835 static int esd_proto_sample_cache(connection *c, esd_proto_t request, const void *data, size_t length) {
837 int32_t format, rate, sc_length;
839 char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1];
841 connection_assert_ref(c);
843 pa_assert(length == (ESD_NAME_MAX+3*sizeof(int32_t)));
845 memcpy(&format, data, sizeof(int32_t));
846 format = PA_MAYBE_INT32_SWAP(c->swap_byte_order, format);
847 data = (const char*)data + sizeof(int32_t);
849 memcpy(&rate, data, sizeof(int32_t));
850 rate = PA_MAYBE_INT32_SWAP(c->swap_byte_order, rate);
851 data = (const char*)data + sizeof(int32_t);
853 ss.rate = (uint32_t) rate;
854 format_esd2native(format, c->swap_byte_order, &ss);
856 CHECK_VALIDITY(pa_sample_spec_valid(&ss), "Invalid sample specification.");
858 memcpy(&sc_length, data, sizeof(int32_t));
859 sc_length = PA_MAYBE_INT32_SWAP(c->swap_byte_order, sc_length);
860 data = (const char*)data + sizeof(int32_t);
862 CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large (%d bytes).", (int)sc_length);
864 strcpy(name, SCACHE_PREFIX);
865 pa_strlcpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
867 CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
869 pa_assert(!c->scache.memchunk.memblock);
870 c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) sc_length);
871 c->scache.memchunk.index = 0;
872 c->scache.memchunk.length = (size_t) sc_length;
873 c->scache.sample_spec = ss;
874 pa_assert(!c->scache.name);
875 c->scache.name = pa_xstrdup(name);
877 c->state = ESD_CACHING_SAMPLE;
879 pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, c->client->proplist, &idx);
882 connection_write(c, &idx, sizeof(uint32_t));
887 static int esd_proto_sample_get_id(connection *c, esd_proto_t request, const void *data, size_t length) {
890 char name[ESD_NAME_MAX+sizeof(SCACHE_PREFIX)-1];
892 connection_assert_ref(c);
894 pa_assert(length == ESD_NAME_MAX);
896 strcpy(name, SCACHE_PREFIX);
897 pa_strlcpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
899 CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
902 if ((idx = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID)
903 ok = (int32_t) idx + 1;
905 connection_write(c, &ok, sizeof(int32_t));
910 static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length) {
915 connection_assert_ref(c);
917 pa_assert(length == sizeof(int32_t));
919 memcpy(&idx, data, sizeof(uint32_t));
920 idx = PA_MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
924 if ((name = pa_scache_get_name_by_id(c->protocol->core, idx))) {
925 if (request == ESD_PROTO_SAMPLE_PLAY) {
928 if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK)))
929 if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM, c->client->proplist, NULL) >= 0)
930 ok = (int32_t) idx + 1;
932 pa_assert(request == ESD_PROTO_SAMPLE_FREE);
934 if (pa_scache_remove_item(c->protocol->core, name) >= 0)
935 ok = (int32_t) idx + 1;
939 connection_write(c, &ok, sizeof(int32_t));
944 static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length) {
947 connection_assert_ref(c);
949 connection_write_prepare(c, sizeof(int32_t) * 2);
950 connection_write(c, &ok, sizeof(int32_t));
952 pa_log_debug("%s of all sinks and sources requested by client %" PRIu32 ".",
953 request == ESD_PROTO_STANDBY ? "Suspending" : "Resuming", c->client->index);
955 if (request == ESD_PROTO_STANDBY) {
956 ok = pa_sink_suspend_all(c->protocol->core, true, PA_SUSPEND_USER) >= 0;
957 ok &= pa_source_suspend_all(c->protocol->core, true, PA_SUSPEND_USER) >= 0;
959 pa_assert(request == ESD_PROTO_RESUME);
960 ok = pa_sink_suspend_all(c->protocol->core, false, PA_SUSPEND_USER) >= 0;
961 ok &= pa_source_suspend_all(c->protocol->core, false, PA_SUSPEND_USER) >= 0;
964 connection_write(c, &ok, sizeof(int32_t));
969 static int esd_proto_standby_mode(connection *c, esd_proto_t request, const void *data, size_t length) {
971 pa_sink *sink, *source;
973 connection_assert_ref(c);
977 if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK)))
978 if (pa_sink_get_state(sink) == PA_SINK_SUSPENDED)
979 mode = ESM_ON_STANDBY;
981 if ((source = pa_namereg_get(c->protocol->core, c->options->default_source, PA_NAMEREG_SOURCE)))
982 if (pa_source_get_state(source) == PA_SOURCE_SUSPENDED)
983 mode = ESM_ON_STANDBY;
985 mode = PA_MAYBE_INT32_SWAP(c->swap_byte_order, mode);
987 connection_write(c, &mode, sizeof(mode));
991 /*** client callbacks ***/
993 static void client_kill_cb(pa_client *c) {
996 connection_unlink(CONNECTION(c->userdata));
999 /*** pa_iochannel callbacks ***/
1001 static int do_read(connection *c) {
1002 connection_assert_ref(c);
1004 /* pa_log("READ"); */
1006 if (c->state == ESD_NEXT_REQUEST) {
1008 pa_assert(c->read_data_length < sizeof(c->request));
1010 if ((r = pa_iochannel_read(c->io,
1011 ((uint8_t*) &c->request) + c->read_data_length,
1012 sizeof(c->request) - c->read_data_length)) <= 0) {
1014 if (r < 0 && (errno == EINTR || errno == EAGAIN))
1017 pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
1021 c->read_data_length += (size_t) r;
1023 if (c->read_data_length >= sizeof(c->request)) {
1024 struct proto_handler *handler;
1026 c->request = PA_MAYBE_INT32_SWAP(c->swap_byte_order, c->request);
1028 if (c->request < ESD_PROTO_CONNECT || c->request >= ESD_PROTO_MAX) {
1029 pa_log("received invalid request.");
1033 handler = proto_map+c->request;
1035 /* pa_log("executing request #%u", c->request); */
1037 if (!handler->proc) {
1038 pa_log("received unimplemented request #%u.", c->request);
1042 if (handler->data_length == 0) {
1043 c->read_data_length = 0;
1045 if (handler->proc(c, c->request, NULL, 0) < 0)
1049 if (c->read_data_alloc < handler->data_length)
1050 c->read_data = pa_xrealloc(c->read_data, c->read_data_alloc = handler->data_length);
1051 pa_assert(c->read_data);
1053 c->state = ESD_NEEDS_REQDATA;
1054 c->read_data_length = 0;
1058 } else if (c->state == ESD_NEEDS_REQDATA) {
1060 struct proto_handler *handler = proto_map+c->request;
1062 pa_assert(handler->proc);
1064 pa_assert(c->read_data && c->read_data_length < handler->data_length);
1066 if ((r = pa_iochannel_read(c->io,
1067 (uint8_t*) c->read_data + c->read_data_length,
1068 handler->data_length - c->read_data_length)) <= 0) {
1070 if (r < 0 && (errno == EINTR || errno == EAGAIN))
1073 pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
1077 c->read_data_length += (size_t) r;
1078 if (c->read_data_length >= handler->data_length) {
1079 size_t l = c->read_data_length;
1080 pa_assert(handler->proc);
1082 c->state = ESD_NEXT_REQUEST;
1083 c->read_data_length = 0;
1085 if (handler->proc(c, c->request, c->read_data, l) < 0)
1088 } else if (c->state == ESD_CACHING_SAMPLE) {
1092 pa_assert(c->scache.memchunk.memblock);
1093 pa_assert(c->scache.name);
1094 pa_assert(c->scache.memchunk.index < c->scache.memchunk.length);
1096 p = pa_memblock_acquire(c->scache.memchunk.memblock);
1097 r = pa_iochannel_read(c->io, (uint8_t*) p+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index);
1098 pa_memblock_release(c->scache.memchunk.memblock);
1101 if (r < 0 && (errno == EINTR || errno == EAGAIN))
1104 pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
1108 c->scache.memchunk.index += (size_t) r;
1109 pa_assert(c->scache.memchunk.index <= c->scache.memchunk.length);
1111 if (c->scache.memchunk.index == c->scache.memchunk.length) {
1114 c->scache.memchunk.index = 0;
1115 pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, c->client->proplist, &idx);
1117 pa_memblock_unref(c->scache.memchunk.memblock);
1118 pa_memchunk_reset(&c->scache.memchunk);
1120 pa_xfree(c->scache.name);
1121 c->scache.name = NULL;
1123 c->state = ESD_NEXT_REQUEST;
1126 connection_write(c, &idx, sizeof(uint32_t));
1129 } else if (c->state == ESD_STREAMING_DATA && c->sink_input) {
1136 pa_assert(c->input_memblockq);
1138 /* pa_log("STREAMING_DATA"); */
1140 if ((l = (size_t) pa_atomic_load(&c->playback.missing)) <= 0)
1143 if (c->playback.current_memblock) {
1145 space = pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index;
1148 pa_memblock_unref(c->playback.current_memblock);
1149 c->playback.current_memblock = NULL;
1153 if (!c->playback.current_memblock) {
1154 pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) -1));
1155 c->playback.memblock_index = 0;
1157 space = pa_memblock_get_length(c->playback.current_memblock);
1163 p = pa_memblock_acquire(c->playback.current_memblock);
1164 r = pa_iochannel_read(c->io, (uint8_t*) p+c->playback.memblock_index, l);
1165 pa_memblock_release(c->playback.current_memblock);
1169 if (r < 0 && (errno == EINTR || errno == EAGAIN))
1172 pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
1176 chunk.memblock = c->playback.current_memblock;
1177 chunk.index = c->playback.memblock_index;
1178 chunk.length = (size_t) r;
1180 c->playback.memblock_index += (size_t) r;
1182 pa_atomic_sub(&c->playback.missing, (int) r);
1183 pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL);
1189 static int do_write(connection *c) {
1190 connection_assert_ref(c);
1192 /* pa_log("WRITE"); */
1194 if (c->write_data_length) {
1197 pa_assert(c->write_data_index < c->write_data_length);
1198 if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) {
1200 if (r < 0 && (errno == EINTR || errno == EAGAIN))
1203 pa_log("write(): %s", pa_cstrerror(errno));
1207 c->write_data_index += (size_t) r;
1208 if (c->write_data_index >= c->write_data_length)
1209 c->write_data_length = c->write_data_index = 0;
1211 } else if (c->state == ESD_STREAMING_DATA && c->source_output) {
1216 if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0)
1219 pa_assert(chunk.memblock);
1220 pa_assert(chunk.length);
1222 p = pa_memblock_acquire(chunk.memblock);
1223 r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length);
1224 pa_memblock_release(chunk.memblock);
1226 pa_memblock_unref(chunk.memblock);
1230 if (r < 0 && (errno == EINTR || errno == EAGAIN))
1233 pa_log("write(): %s", pa_cstrerror(errno));
1237 pa_memblockq_drop(c->output_memblockq, (size_t) r);
1243 static void do_work(connection *c) {
1244 connection_assert_ref(c);
1246 c->protocol->core->mainloop->defer_enable(c->defer_event, 0);
1251 if (pa_iochannel_is_readable(c->io))
1255 if (c->state == ESD_STREAMING_DATA && !c->sink_input && pa_iochannel_is_hungup(c->io))
1256 /* In case we are in capture mode we will never call read()
1257 * on the socket, hence we need to detect the hangup manually
1258 * here, instead of simply waiting for read() to return 0. */
1261 if (pa_iochannel_is_writable(c->io))
1262 if (do_write(c) < 0)
1269 if (c->state == ESD_STREAMING_DATA && c->sink_input) {
1272 pa_iochannel_free(c->io);
1275 pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL);
1277 connection_unlink(c);
1280 static void io_callback(pa_iochannel*io, void *userdata) {
1281 connection *c = CONNECTION(userdata);
1283 connection_assert_ref(c);
1289 static void defer_callback(pa_mainloop_api*a, pa_defer_event *e, void *userdata) {
1290 connection *c = CONNECTION(userdata);
1292 connection_assert_ref(c);
1298 static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
1299 connection *c = CONNECTION(o);
1300 connection_assert_ref(c);
1306 case CONNECTION_MESSAGE_REQUEST_DATA:
1310 case CONNECTION_MESSAGE_POST_DATA:
1311 /* pa_log("got data %u", chunk->length); */
1312 pa_memblockq_push_align(c->output_memblockq, chunk);
1316 case CONNECTION_MESSAGE_UNLINK_CONNECTION:
1317 connection_unlink(c);
1324 /*** sink_input callbacks ***/
1326 /* Called from thread context */
1327 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1328 pa_sink_input *i = PA_SINK_INPUT(o);
1331 pa_sink_input_assert_ref(i);
1332 c = CONNECTION(i->userdata);
1333 connection_assert_ref(c);
1337 case SINK_INPUT_MESSAGE_POST_DATA: {
1340 /* New data from the main loop */
1341 pa_memblockq_push_align(c->input_memblockq, chunk);
1343 if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) {
1344 pa_log_debug("Requesting rewind due to end of underrun.");
1345 pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE, FALSE);
1348 /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
1353 case SINK_INPUT_MESSAGE_DISABLE_PREBUF:
1354 pa_memblockq_prebuf_disable(c->input_memblockq);
1357 case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1358 pa_usec_t *r = userdata;
1360 *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
1362 /* Fall through, the default handler will add in the extra
1363 * latency added by the resampler */
1367 return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1371 /* Called from thread context */
1372 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
1375 pa_sink_input_assert_ref(i);
1376 c = CONNECTION(i->userdata);
1377 connection_assert_ref(c);
1380 if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
1382 c->playback.underrun = TRUE;
1384 if (c->dead && pa_sink_input_safe_to_remove(i))
1385 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
1391 c->playback.underrun = FALSE;
1393 chunk->length = PA_MIN(length, chunk->length);
1394 pa_memblockq_drop(c->input_memblockq, chunk->length);
1395 m = pa_memblockq_pop_missing(c->input_memblockq);
1398 if (pa_atomic_add(&c->playback.missing, (int) m) <= 0)
1399 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
1405 /* Called from thread context */
1406 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1409 pa_sink_input_assert_ref(i);
1410 c = CONNECTION(i->userdata);
1411 connection_assert_ref(c);
1413 /* If we are in an underrun, then we don't rewind */
1414 if (i->thread_info.underrun_for > 0)
1417 pa_memblockq_rewind(c->input_memblockq, nbytes);
1420 /* Called from thread context */
1421 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1424 pa_sink_input_assert_ref(i);
1425 c = CONNECTION(i->userdata);
1426 connection_assert_ref(c);
1428 pa_memblockq_set_maxrewind(c->input_memblockq, nbytes);
1431 static void sink_input_kill_cb(pa_sink_input *i) {
1432 pa_sink_input_assert_ref(i);
1434 connection_unlink(CONNECTION(i->userdata));
1437 /*** source_output callbacks ***/
1439 /* Called from thread context */
1440 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1443 pa_source_output_assert_ref(o);
1444 c = CONNECTION(o->userdata);
1448 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1451 static void source_output_kill_cb(pa_source_output *o) {
1452 pa_source_output_assert_ref(o);
1454 connection_unlink(CONNECTION(o->userdata));
1457 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1460 pa_source_output_assert_ref(o);
1461 c = CONNECTION(o->userdata);
1464 return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec);
1467 /*** entry points ***/
1469 static void auth_timeout(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
1470 connection *c = CONNECTION(userdata);
1473 connection_assert_ref(c);
1474 pa_assert(c->auth_timeout_event == e);
1477 connection_unlink(c);
1480 void pa_esound_protocol_connect(pa_esound_protocol *p, pa_iochannel *io, pa_esound_options *o) {
1483 pa_client_new_data data;
1490 if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
1491 pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
1492 pa_iochannel_free(io);
1496 pa_client_new_data_init(&data);
1497 data.module = o->module;
1498 data.driver = __FILE__;
1499 pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
1500 pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "EsounD client (%s)", pname);
1501 pa_proplist_sets(data.proplist, "esound-protocol.peer", pname);
1502 client = pa_client_new(p->core, &data);
1503 pa_client_new_data_done(&data);
1508 c = pa_msgobject_new(connection);
1509 c->parent.parent.free = connection_free;
1510 c->parent.process_msg = connection_process_msg;
1513 pa_iochannel_set_callback(c->io, io_callback, c);
1516 c->client->kill = client_kill_cb;
1517 c->client->userdata = c;
1519 c->options = pa_esound_options_ref(o);
1520 c->authorized = FALSE;
1521 c->swap_byte_order = FALSE;
1524 c->read_data_length = 0;
1525 c->read_data = pa_xmalloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length);
1527 c->write_data_length = c->write_data_index = c->write_data_alloc = 0;
1528 c->write_data = NULL;
1530 c->state = ESD_NEEDS_REQDATA;
1531 c->request = ESD_PROTO_CONNECT;
1533 c->sink_input = NULL;
1534 c->input_memblockq = NULL;
1536 c->source_output = NULL;
1537 c->output_memblockq = NULL;
1539 c->playback.current_memblock = NULL;
1540 c->playback.memblock_index = 0;
1541 c->playback.underrun = TRUE;
1542 pa_atomic_store(&c->playback.missing, 0);
1544 pa_memchunk_reset(&c->scache.memchunk);
1545 c->scache.name = NULL;
1547 c->original_name = NULL;
1549 if (o->auth_anonymous) {
1550 pa_log_info("Client authenticated anonymously.");
1551 c->authorized = TRUE;
1554 if (!c->authorized &&
1556 pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
1558 pa_log_info("Client authenticated by IP ACL.");
1559 c->authorized = TRUE;
1563 c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
1565 c->auth_timeout_event = NULL;
1567 c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c);
1568 p->core->mainloop->defer_enable(c->defer_event, 0);
1570 pa_idxset_put(p->connections, c, &c->index);
1573 void pa_esound_protocol_disconnect(pa_esound_protocol *p, pa_module *m) {
1580 while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
1581 if (c->options->module == m)
1582 connection_unlink(c);
1585 static pa_esound_protocol* esound_protocol_new(pa_core *c) {
1586 pa_esound_protocol *p;
1590 p = pa_xnew(pa_esound_protocol, 1);
1593 p->connections = pa_idxset_new(NULL, NULL);
1596 pa_assert_se(pa_shared_set(c, "esound-protocol", p) >= 0);
1601 pa_esound_protocol* pa_esound_protocol_get(pa_core *c) {
1602 pa_esound_protocol *p;
1604 if ((p = pa_shared_get(c, "esound-protocol")))
1605 return pa_esound_protocol_ref(p);
1607 return esound_protocol_new(c);
1610 pa_esound_protocol* pa_esound_protocol_ref(pa_esound_protocol *p) {
1612 pa_assert(PA_REFCNT_VALUE(p) >= 1);
1619 void pa_esound_protocol_unref(pa_esound_protocol *p) {
1622 pa_assert(PA_REFCNT_VALUE(p) >= 1);
1624 if (PA_REFCNT_DEC(p) > 0)
1627 while ((c = pa_idxset_first(p->connections, NULL)))
1628 connection_unlink(c);
1630 pa_idxset_free(p->connections, NULL, NULL);
1632 pa_assert_se(pa_shared_remove(p->core, "esound-protocol") >= 0);
1637 pa_esound_options* pa_esound_options_new(void) {
1638 pa_esound_options *o;
1640 o = pa_xnew0(pa_esound_options, 1);
1646 pa_esound_options* pa_esound_options_ref(pa_esound_options *o) {
1648 pa_assert(PA_REFCNT_VALUE(o) >= 1);
1655 void pa_esound_options_unref(pa_esound_options *o) {
1657 pa_assert(PA_REFCNT_VALUE(o) >= 1);
1659 if (PA_REFCNT_DEC(o) > 0)
1663 pa_ip_acl_free(o->auth_ip_acl);
1666 pa_auth_cookie_unref(o->auth_cookie);
1668 pa_xfree(o->default_sink);
1669 pa_xfree(o->default_source);
1674 int pa_esound_options_parse(pa_esound_options *o, pa_core *c, pa_modargs *ma) {
1679 pa_assert(PA_REFCNT_VALUE(o) >= 1);
1682 if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
1683 pa_log("auth-anonymous= expects a boolean argument.");
1687 if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
1690 if (!(ipa = pa_ip_acl_new(acl))) {
1691 pa_log("Failed to parse IP ACL '%s'", acl);
1696 pa_ip_acl_free(o->auth_ip_acl);
1698 o->auth_ip_acl = ipa;
1702 if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
1703 pa_log("auth-cookie-enabled= expects a boolean argument.");
1708 pa_auth_cookie_unref(o->auth_cookie);
1713 /* The new name for this is 'auth-cookie', for compat reasons
1714 * we check the old name too */
1715 if (!(cn = pa_modargs_get_value(ma, "auth-cookie", NULL)))
1716 if (!(cn = pa_modargs_get_value(ma, "cookie", NULL)))
1717 cn = DEFAULT_COOKIE_FILE;
1719 if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, TRUE, ESD_KEY_LEN)))
1723 o->auth_cookie = NULL;
1725 pa_xfree(o->default_sink);
1726 o->default_sink = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
1728 pa_xfree(o->default_source);
1729 o->default_source = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));