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
33 #include <pulse/rtclock.h>
34 #include <pulse/sample.h>
35 #include <pulse/timeval.h>
36 #include <pulse/utf8.h>
37 #include <pulse/xmalloc.h>
38 #include <pulse/proplist.h>
40 #include <pulsecore/esound.h>
41 #include <pulsecore/memblock.h>
42 #include <pulsecore/client.h>
43 #include <pulsecore/sink-input.h>
44 #include <pulsecore/sink.h>
45 #include <pulsecore/source-output.h>
46 #include <pulsecore/source.h>
47 #include <pulsecore/core-scache.h>
48 #include <pulsecore/sample-util.h>
49 #include <pulsecore/authkey.h>
50 #include <pulsecore/namereg.h>
51 #include <pulsecore/log.h>
52 #include <pulsecore/core-util.h>
53 #include <pulsecore/core-error.h>
54 #include <pulsecore/ipacl.h>
55 #include <pulsecore/macro.h>
56 #include <pulsecore/thread-mq.h>
57 #include <pulsecore/shared.h>
59 #include "endianmacros.h"
61 #include "protocol-esound.h"
63 /* Don't accept more connection than this */
64 #define MAX_CONNECTIONS 64
66 /* Kick a client if it doesn't authenticate within this time */
67 #define AUTH_TIMEOUT (5*PA_USEC_PER_SEC)
69 #define DEFAULT_COOKIE_FILE ".esd_auth"
71 #define PLAYBACK_BUFFER_SECONDS (.25)
72 #define PLAYBACK_BUFFER_FRAGMENTS (10)
73 #define RECORD_BUFFER_SECONDS (5)
75 #define MAX_CACHE_SAMPLE_SIZE (2048000)
77 #define DEFAULT_SINK_LATENCY (150*PA_USEC_PER_MSEC)
78 #define DEFAULT_SOURCE_LATENCY (150*PA_USEC_PER_MSEC)
80 #define SCACHE_PREFIX "esound."
82 /* This is heavily based on esound's code */
84 typedef struct connection
{
89 pa_esound_protocol
*protocol
;
90 pa_esound_options
*options
;
93 pa_bool_t authorized
, swap_byte_order
;
95 size_t write_data_alloc
, write_data_index
, write_data_length
;
97 size_t read_data_alloc
, read_data_length
;
99 esd_client_state_t state
;
100 pa_sink_input
*sink_input
;
101 pa_source_output
*source_output
;
102 pa_memblockq
*input_memblockq
, *output_memblockq
;
103 pa_defer_event
*defer_event
;
108 pa_memblock
*current_memblock
;
109 size_t memblock_index
;
115 pa_memchunk memchunk
;
117 pa_sample_spec sample_spec
;
120 pa_time_event
*auth_timeout_event
;
123 PA_DECLARE_CLASS(connection
);
124 #define CONNECTION(o) (connection_cast(o))
125 static PA_DEFINE_CHECK_TYPE(connection
, pa_msgobject
);
127 struct pa_esound_protocol
{
131 pa_idxset
*connections
;
136 SINK_INPUT_MESSAGE_POST_DATA
= PA_SINK_INPUT_MESSAGE_MAX
, /* data from main loop to sink input */
137 SINK_INPUT_MESSAGE_DISABLE_PREBUF
141 CONNECTION_MESSAGE_REQUEST_DATA
,
142 CONNECTION_MESSAGE_POST_DATA
,
143 CONNECTION_MESSAGE_UNLINK_CONNECTION
146 typedef struct proto_handler
{
148 int (*proc
)(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
149 const char *description
;
150 } esd_proto_handler_info_t
;
152 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
);
153 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
154 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
155 static void sink_input_kill_cb(pa_sink_input
*i
);
156 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
157 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
159 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
160 static void source_output_kill_cb(pa_source_output
*o
);
162 static int esd_proto_connect(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
163 static int esd_proto_stream_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
164 static int esd_proto_stream_record(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
165 static int esd_proto_get_latency(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
166 static int esd_proto_server_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
167 static int esd_proto_all_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
168 static int esd_proto_stream_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
169 static int esd_proto_sample_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
170 static int esd_proto_sample_cache(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
171 static int esd_proto_sample_free_or_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
172 static int esd_proto_sample_get_id(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
173 static int esd_proto_standby_or_resume(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
174 static int esd_proto_standby_mode(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
176 /* the big map of protocol handler info */
177 static struct proto_handler proto_map
[ESD_PROTO_MAX
] = {
178 { ESD_KEY_LEN
+ sizeof(int), esd_proto_connect
, "connect" },
179 { ESD_KEY_LEN
+ sizeof(int), NULL
, "lock" },
180 { ESD_KEY_LEN
+ sizeof(int), NULL
, "unlock" },
182 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_play
, "stream play" },
183 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream rec" },
184 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream mon" },
186 { ESD_NAME_MAX
+ 3 * sizeof(int), esd_proto_sample_cache
, "sample cache" }, /* 6 */
187 { sizeof(int), esd_proto_sample_free_or_play
, "sample free" },
188 { sizeof(int), esd_proto_sample_free_or_play
, "sample play" }, /* 8 */
189 { sizeof(int), NULL
, "sample loop" },
190 { sizeof(int), NULL
, "sample stop" },
191 { (size_t) -1, NULL
, "TODO: sample kill" },
193 { ESD_KEY_LEN
+ sizeof(int), esd_proto_standby_or_resume
, "standby" },
194 { ESD_KEY_LEN
+ sizeof(int), esd_proto_standby_or_resume
, "resume" }, /* 13 */
196 { ESD_NAME_MAX
, esd_proto_sample_get_id
, "sample getid" }, /* 14 */
197 { ESD_NAME_MAX
+ 2 * sizeof(int), NULL
, "stream filter" },
199 { sizeof(int), esd_proto_server_info
, "server info" },
200 { sizeof(int), esd_proto_all_info
, "all info" },
201 { (size_t) -1, NULL
, "TODO: subscribe" },
202 { (size_t) -1, NULL
, "TODO: unsubscribe" },
204 { 3 * sizeof(int), esd_proto_stream_pan
, "stream pan"},
205 { 3 * sizeof(int), esd_proto_sample_pan
, "sample pan" },
207 { sizeof(int), esd_proto_standby_mode
, "standby mode" },
208 { 0, esd_proto_get_latency
, "get latency" }
211 static void connection_unlink(connection
*c
) {
218 pa_esound_options_unref(c
->options
);
223 pa_sink_input_unlink(c
->sink_input
);
224 pa_sink_input_unref(c
->sink_input
);
225 c
->sink_input
= NULL
;
228 if (c
->source_output
) {
229 pa_source_output_unlink(c
->source_output
);
230 pa_source_output_unref(c
->source_output
);
231 c
->source_output
= NULL
;
235 pa_client_free(c
->client
);
239 if (c
->state
== ESD_STREAMING_DATA
)
240 c
->protocol
->n_player
--;
243 pa_iochannel_free(c
->io
);
247 if (c
->defer_event
) {
248 c
->protocol
->core
->mainloop
->defer_free(c
->defer_event
);
249 c
->defer_event
= NULL
;
252 if (c
->auth_timeout_event
) {
253 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
254 c
->auth_timeout_event
= NULL
;
257 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
262 static void connection_free(pa_object
*obj
) {
263 connection
*c
= CONNECTION(obj
);
266 if (c
->input_memblockq
)
267 pa_memblockq_free(c
->input_memblockq
);
268 if (c
->output_memblockq
)
269 pa_memblockq_free(c
->output_memblockq
);
271 if (c
->playback
.current_memblock
)
272 pa_memblock_unref(c
->playback
.current_memblock
);
274 pa_xfree(c
->read_data
);
275 pa_xfree(c
->write_data
);
277 if (c
->scache
.memchunk
.memblock
)
278 pa_memblock_unref(c
->scache
.memchunk
.memblock
);
279 pa_xfree(c
->scache
.name
);
281 pa_xfree(c
->original_name
);
285 static void connection_write_prepare(connection
*c
, size_t length
) {
289 t
= c
->write_data_length
+length
;
291 if (c
->write_data_alloc
< t
)
292 c
->write_data
= pa_xrealloc(c
->write_data
, c
->write_data_alloc
= t
);
294 pa_assert(c
->write_data
);
297 static void connection_write(connection
*c
, const void *data
, size_t length
) {
301 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
303 connection_write_prepare(c
, length
);
305 pa_assert(c
->write_data
);
307 i
= c
->write_data_length
;
308 c
->write_data_length
+= length
;
310 memcpy((uint8_t*) c
->write_data
+ i
, data
, length
);
313 static void format_esd2native(int format
, pa_bool_t swap_bytes
, pa_sample_spec
*ss
) {
316 ss
->channels
= (uint8_t) (((format
& ESD_MASK_CHAN
) == ESD_STEREO
) ? 2 : 1);
317 if ((format
& ESD_MASK_BITS
) == ESD_BITS16
)
318 ss
->format
= swap_bytes
? PA_SAMPLE_S16RE
: PA_SAMPLE_S16NE
;
320 ss
->format
= PA_SAMPLE_U8
;
323 static int format_native2esd(pa_sample_spec
*ss
) {
326 format
= (ss
->format
== PA_SAMPLE_U8
) ? ESD_BITS8
: ESD_BITS16
;
327 format
|= (ss
->channels
>= 2) ? ESD_STEREO
: ESD_MONO
;
332 #define CHECK_VALIDITY(expression, ...) do { \
333 if (!(expression)) { \
334 pa_log_warn(__FILE__ ": " __VA_ARGS__); \
339 /*** esound commands ***/
341 static int esd_proto_connect(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
345 connection_assert_ref(c
);
347 pa_assert(length
== (ESD_KEY_LEN
+ sizeof(uint32_t)));
349 if (!c
->authorized
&& c
->options
->auth_cookie
) {
352 if ((key
= pa_auth_cookie_read(c
->options
->auth_cookie
, ESD_KEY_LEN
)))
353 if (memcmp(data
, key
, ESD_KEY_LEN
) == 0)
354 c
->authorized
= TRUE
;
357 if (!c
->authorized
) {
358 pa_log("Kicked client with invalid authorization key.");
362 if (c
->auth_timeout_event
) {
363 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
364 c
->auth_timeout_event
= NULL
;
367 data
= (const char*)data
+ ESD_KEY_LEN
;
369 memcpy(&ekey
, data
, sizeof(uint32_t));
370 if (ekey
== ESD_ENDIAN_KEY
)
371 c
->swap_byte_order
= FALSE
;
372 else if (ekey
== ESD_SWAP_ENDIAN_KEY
)
373 c
->swap_byte_order
= TRUE
;
375 pa_log_warn("Client sent invalid endian key");
379 pa_proplist_sets(c
->client
->proplist
, "esound.byte_order", c
->swap_byte_order
? "reverse" : "native");
382 connection_write(c
, &ok
, sizeof(int));
386 static int esd_proto_stream_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
387 char name
[ESD_NAME_MAX
], *utf8_name
;
388 int32_t format
, rate
;
391 pa_sink
*sink
= NULL
;
392 pa_sink_input_new_data sdata
;
394 connection_assert_ref(c
);
396 pa_assert(length
== (sizeof(int32_t)*2+ESD_NAME_MAX
));
398 memcpy(&format
, data
, sizeof(int32_t));
399 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
400 data
= (const char*) data
+ sizeof(int32_t);
402 memcpy(&rate
, data
, sizeof(int32_t));
403 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
404 data
= (const char*) data
+ sizeof(int32_t);
406 ss
.rate
= (uint32_t) rate
;
407 format_esd2native(format
, c
->swap_byte_order
, &ss
);
409 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification");
411 if (c
->options
->default_sink
) {
412 sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
);
413 CHECK_VALIDITY(sink
, "No such sink: %s", pa_strnull(c
->options
->default_sink
));
416 pa_strlcpy(name
, data
, sizeof(name
));
418 utf8_name
= pa_utf8_filter(name
);
419 pa_client_set_name(c
->client
, utf8_name
);
422 c
->original_name
= pa_xstrdup(name
);
424 pa_assert(!c
->sink_input
&& !c
->input_memblockq
);
426 pa_sink_input_new_data_init(&sdata
);
427 sdata
.driver
= __FILE__
;
428 sdata
.module
= c
->options
->module
;
429 sdata
.client
= c
->client
;
431 pa_sink_input_new_data_set_sample_spec(&sdata
, &ss
);
433 pa_sink_input_new(&c
->sink_input
, c
->protocol
->core
, &sdata
, 0);
434 pa_sink_input_new_data_done(&sdata
);
436 CHECK_VALIDITY(c
->sink_input
, "Failed to create sink input.");
438 l
= (size_t) ((double) pa_bytes_per_second(&ss
)*PLAYBACK_BUFFER_SECONDS
);
439 c
->input_memblockq
= pa_memblockq_new(
445 l
/PLAYBACK_BUFFER_FRAGMENTS
,
448 pa_iochannel_socket_set_rcvbuf(c
->io
, l
);
450 c
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
451 c
->sink_input
->pop
= sink_input_pop_cb
;
452 c
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
453 c
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
454 c
->sink_input
->kill
= sink_input_kill_cb
;
455 c
->sink_input
->userdata
= c
;
457 pa_sink_input_set_requested_latency(c
->sink_input
, DEFAULT_SINK_LATENCY
);
459 c
->state
= ESD_STREAMING_DATA
;
461 c
->protocol
->n_player
++;
463 pa_atomic_store(&c
->playback
.missing
, (int) pa_memblockq_missing(c
->input_memblockq
));
465 pa_sink_input_put(c
->sink_input
);
470 static int esd_proto_stream_record(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
471 char name
[ESD_NAME_MAX
], *utf8_name
;
472 int32_t format
, rate
;
473 pa_source
*source
= NULL
;
476 pa_source_output_new_data sdata
;
478 connection_assert_ref(c
);
480 pa_assert(length
== (sizeof(int32_t)*2+ESD_NAME_MAX
));
482 memcpy(&format
, data
, sizeof(int32_t));
483 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
484 data
= (const char*) data
+ sizeof(int32_t);
486 memcpy(&rate
, data
, sizeof(int32_t));
487 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
488 data
= (const char*) data
+ sizeof(int32_t);
490 ss
.rate
= (uint32_t) rate
;
491 format_esd2native(format
, c
->swap_byte_order
, &ss
);
493 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification.");
495 if (request
== ESD_PROTO_STREAM_MON
) {
498 sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
);
499 CHECK_VALIDITY(sink
, "No such sink: %s", pa_strnull(c
->options
->default_sink
));
501 source
= sink
->monitor_source
;
502 CHECK_VALIDITY(source
, "No such source.");
504 pa_assert(request
== ESD_PROTO_STREAM_REC
);
506 if (c
->options
->default_source
) {
507 source
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_source
, PA_NAMEREG_SOURCE
);
508 CHECK_VALIDITY(source
, "No such source: %s", pa_strnull(c
->options
->default_source
));
512 pa_strlcpy(name
, data
, sizeof(name
));
514 utf8_name
= pa_utf8_filter(name
);
515 pa_client_set_name(c
->client
, utf8_name
);
518 c
->original_name
= pa_xstrdup(name
);
520 pa_assert(!c
->output_memblockq
&& !c
->source_output
);
522 pa_source_output_new_data_init(&sdata
);
523 sdata
.driver
= __FILE__
;
524 sdata
.module
= c
->options
->module
;
525 sdata
.client
= c
->client
;
526 sdata
.source
= source
;
527 pa_source_output_new_data_set_sample_spec(&sdata
, &ss
);
529 pa_source_output_new(&c
->source_output
, c
->protocol
->core
, &sdata
, 0);
530 pa_source_output_new_data_done(&sdata
);
532 CHECK_VALIDITY(c
->source_output
, "Failed to create source output.");
534 l
= (size_t) (pa_bytes_per_second(&ss
)*RECORD_BUFFER_SECONDS
);
535 c
->output_memblockq
= pa_memblockq_new(
544 pa_iochannel_socket_set_sndbuf(c
->io
, l
);
546 c
->source_output
->push
= source_output_push_cb
;
547 c
->source_output
->kill
= source_output_kill_cb
;
548 c
->source_output
->get_latency
= source_output_get_latency_cb
;
549 c
->source_output
->userdata
= c
;
551 pa_source_output_set_requested_latency(c
->source_output
, DEFAULT_SOURCE_LATENCY
);
553 c
->state
= ESD_STREAMING_DATA
;
555 c
->protocol
->n_player
++;
557 pa_source_output_put(c
->source_output
);
562 static int esd_proto_get_latency(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
566 connection_assert_ref(c
);
568 pa_assert(length
== 0);
570 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
573 double usec
= (double) pa_sink_get_requested_latency(sink
);
574 latency
= (int) ((usec
*44100)/1000000);
577 latency
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, latency
);
578 connection_write(c
, &latency
, sizeof(int32_t));
583 static int esd_proto_server_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
584 int32_t rate
= 44100, format
= ESD_STEREO
|ESD_BITS16
;
588 connection_assert_ref(c
);
590 pa_assert(length
== sizeof(int32_t));
592 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
))) {
593 rate
= (int32_t) sink
->sample_spec
.rate
;
594 format
= format_native2esd(&sink
->sample_spec
);
597 connection_write_prepare(c
, sizeof(int32_t) * 3);
600 connection_write(c
, &response
, sizeof(int32_t));
601 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
602 connection_write(c
, &rate
, sizeof(int32_t));
603 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
604 connection_write(c
, &format
, sizeof(int32_t));
609 static int esd_proto_all_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
612 uint32_t idx
= PA_IDXSET_INVALID
;
614 char terminator
[sizeof(int32_t)*6+ESD_NAME_MAX
];
616 connection_assert_ref(c
);
618 pa_assert(length
== sizeof(int32_t));
620 if (esd_proto_server_info(c
, request
, data
, length
) < 0)
623 k
= sizeof(int32_t)*5+ESD_NAME_MAX
;
624 s
= sizeof(int32_t)*6+ESD_NAME_MAX
;
625 nsamples
= pa_idxset_size(c
->protocol
->core
->scache
);
626 t
= s
*(nsamples
+1) + k
*(c
->protocol
->n_player
+1);
628 connection_write_prepare(c
, t
);
630 memset(terminator
, 0, sizeof(terminator
));
632 for (conn
= pa_idxset_first(c
->protocol
->connections
, &idx
); conn
; conn
= pa_idxset_next(c
->protocol
->connections
, &idx
)) {
633 int32_t id
, format
= ESD_BITS16
| ESD_STEREO
, rate
= 44100, lvolume
= ESD_VOLUME_BASE
, rvolume
= ESD_VOLUME_BASE
;
634 char name
[ESD_NAME_MAX
];
636 if (conn
->state
!= ESD_STREAMING_DATA
)
639 pa_assert(t
>= k
*2+s
);
641 if (conn
->sink_input
) {
643 pa_sink_input_get_volume(conn
->sink_input
, &volume
, TRUE
);
644 rate
= (int32_t) conn
->sink_input
->sample_spec
.rate
;
645 lvolume
= (int32_t) ((volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
646 rvolume
= (int32_t) ((volume
.values
[volume
.channels
== 2 ? 1 : 0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
647 format
= format_native2esd(&conn
->sink_input
->sample_spec
);
651 id
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) (conn
->index
+1));
652 connection_write(c
, &id
, sizeof(int32_t));
655 memset(name
, 0, ESD_NAME_MAX
); /* don't leak old data */
656 if (conn
->original_name
)
657 strncpy(name
, conn
->original_name
, ESD_NAME_MAX
);
658 else if (conn
->client
&& pa_proplist_gets(conn
->client
->proplist
, PA_PROP_APPLICATION_NAME
))
659 strncpy(name
, pa_proplist_gets(conn
->client
->proplist
, PA_PROP_APPLICATION_NAME
), ESD_NAME_MAX
);
660 connection_write(c
, name
, ESD_NAME_MAX
);
663 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
664 connection_write(c
, &rate
, sizeof(int32_t));
667 lvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, lvolume
);
668 connection_write(c
, &lvolume
, sizeof(int32_t));
671 rvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rvolume
);
672 connection_write(c
, &rvolume
, sizeof(int32_t));
675 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
676 connection_write(c
, &format
, sizeof(int32_t));
681 pa_assert(t
== s
*(nsamples
+1)+k
);
684 connection_write(c
, terminator
, k
);
689 idx
= PA_IDXSET_INVALID
;
690 for (ce
= pa_idxset_first(c
->protocol
->core
->scache
, &idx
); ce
; ce
= pa_idxset_next(c
->protocol
->core
->scache
, &idx
)) {
691 int32_t id
, rate
, lvolume
, rvolume
, format
, len
;
692 char name
[ESD_NAME_MAX
];
693 pa_channel_map stereo
= { .channels
= 2, .map
= { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
} };
699 if (ce
->volume_is_set
) {
701 pa_cvolume_remap(&volume
, &ce
->channel_map
, &stereo
);
703 pa_cvolume_reset(&volume
, 2);
705 if (ce
->memchunk
.memblock
)
706 ss
= ce
->sample_spec
;
708 ss
.format
= PA_SAMPLE_S16NE
;
714 id
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) (ce
->index
+1));
715 connection_write(c
, &id
, sizeof(int32_t));
718 memset(name
, 0, ESD_NAME_MAX
); /* don't leak old data */
719 if (strncmp(ce
->name
, SCACHE_PREFIX
, sizeof(SCACHE_PREFIX
)-1) == 0)
720 strncpy(name
, ce
->name
+sizeof(SCACHE_PREFIX
)-1, ESD_NAME_MAX
);
722 pa_snprintf(name
, ESD_NAME_MAX
, "native.%s", ce
->name
);
723 connection_write(c
, name
, ESD_NAME_MAX
);
726 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ss
.rate
);
727 connection_write(c
, &rate
, sizeof(int32_t));
730 lvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ((volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
));
731 connection_write(c
, &lvolume
, sizeof(int32_t));
734 rvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ((volume
.values
[1]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
));
735 connection_write(c
, &rvolume
, sizeof(int32_t));
738 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format_native2esd(&ss
));
739 connection_write(c
, &format
, sizeof(int32_t));
742 len
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) ce
->memchunk
.length
);
743 connection_write(c
, &len
, sizeof(int32_t));
751 connection_write(c
, terminator
, s
);
756 static int esd_proto_stream_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
758 uint32_t idx
, lvolume
, rvolume
;
761 connection_assert_ref(c
);
763 pa_assert(length
== sizeof(int32_t)*3);
765 memcpy(&idx
, data
, sizeof(uint32_t));
766 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
767 data
= (const char*)data
+ sizeof(uint32_t);
769 memcpy(&lvolume
, data
, sizeof(uint32_t));
770 lvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
771 data
= (const char*)data
+ sizeof(uint32_t);
773 memcpy(&rvolume
, data
, sizeof(uint32_t));
774 rvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
775 data
= (const char*)data
+ sizeof(uint32_t);
777 if ((conn
= pa_idxset_get_by_index(c
->protocol
->connections
, idx
)) && conn
->sink_input
) {
779 volume
.values
[0] = (lvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
780 volume
.values
[1] = (rvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
781 volume
.channels
= conn
->sink_input
->sample_spec
.channels
;
783 pa_sink_input_set_volume(conn
->sink_input
, &volume
, TRUE
, TRUE
);
788 connection_write(c
, &ok
, sizeof(int32_t));
793 static int esd_proto_sample_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
795 uint32_t idx
, lvolume
, rvolume
;
799 connection_assert_ref(c
);
801 pa_assert(length
== sizeof(int32_t)*3);
803 memcpy(&idx
, data
, sizeof(uint32_t));
804 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
805 data
= (const char*)data
+ sizeof(uint32_t);
807 memcpy(&lvolume
, data
, sizeof(uint32_t));
808 lvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
809 data
= (const char*)data
+ sizeof(uint32_t);
811 memcpy(&rvolume
, data
, sizeof(uint32_t));
812 rvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
813 data
= (const char*)data
+ sizeof(uint32_t);
815 volume
.values
[0] = (lvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
816 volume
.values
[1] = (rvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
819 if ((ce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
))) {
820 pa_channel_map stereo
= { .channels
= 2, .map
= { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
} };
822 pa_cvolume_remap(&volume
, &stereo
, &ce
->channel_map
);
824 ce
->volume_is_set
= TRUE
;
828 connection_write(c
, &ok
, sizeof(int32_t));
833 static int esd_proto_sample_cache(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
835 int32_t format
, rate
, sc_length
;
837 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
839 connection_assert_ref(c
);
841 pa_assert(length
== (ESD_NAME_MAX
+3*sizeof(int32_t)));
843 memcpy(&format
, data
, sizeof(int32_t));
844 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
845 data
= (const char*)data
+ sizeof(int32_t);
847 memcpy(&rate
, data
, sizeof(int32_t));
848 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
849 data
= (const char*)data
+ sizeof(int32_t);
851 ss
.rate
= (uint32_t) rate
;
852 format_esd2native(format
, c
->swap_byte_order
, &ss
);
854 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification.");
856 memcpy(&sc_length
, data
, sizeof(int32_t));
857 sc_length
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, sc_length
);
858 data
= (const char*)data
+ sizeof(int32_t);
860 CHECK_VALIDITY(sc_length
<= MAX_CACHE_SAMPLE_SIZE
, "Sample too large (%d bytes).", (int)sc_length
);
862 strcpy(name
, SCACHE_PREFIX
);
863 pa_strlcpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
865 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in sample name.");
867 pa_assert(!c
->scache
.memchunk
.memblock
);
868 c
->scache
.memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, (size_t) sc_length
);
869 c
->scache
.memchunk
.index
= 0;
870 c
->scache
.memchunk
.length
= (size_t) sc_length
;
871 c
->scache
.sample_spec
= ss
;
872 pa_assert(!c
->scache
.name
);
873 c
->scache
.name
= pa_xstrdup(name
);
875 c
->state
= ESD_CACHING_SAMPLE
;
877 pa_scache_add_item(c
->protocol
->core
, c
->scache
.name
, NULL
, NULL
, NULL
, c
->client
->proplist
, &idx
);
880 connection_write(c
, &idx
, sizeof(uint32_t));
885 static int esd_proto_sample_get_id(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
888 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
890 connection_assert_ref(c
);
892 pa_assert(length
== ESD_NAME_MAX
);
894 strcpy(name
, SCACHE_PREFIX
);
895 pa_strlcpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
897 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in sample name.");
900 if ((idx
= pa_scache_get_id_by_name(c
->protocol
->core
, name
)) != PA_IDXSET_INVALID
)
901 ok
= (int32_t) idx
+ 1;
903 connection_write(c
, &ok
, sizeof(int32_t));
908 static int esd_proto_sample_free_or_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
913 connection_assert_ref(c
);
915 pa_assert(length
== sizeof(int32_t));
917 memcpy(&idx
, data
, sizeof(uint32_t));
918 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
922 if ((name
= pa_scache_get_name_by_id(c
->protocol
->core
, idx
))) {
923 if (request
== ESD_PROTO_SAMPLE_PLAY
) {
926 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
927 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, PA_VOLUME_NORM
, c
->client
->proplist
, NULL
) >= 0)
928 ok
= (int32_t) idx
+ 1;
930 pa_assert(request
== ESD_PROTO_SAMPLE_FREE
);
932 if (pa_scache_remove_item(c
->protocol
->core
, name
) >= 0)
933 ok
= (int32_t) idx
+ 1;
937 connection_write(c
, &ok
, sizeof(int32_t));
942 static int esd_proto_standby_or_resume(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
945 connection_assert_ref(c
);
947 connection_write_prepare(c
, sizeof(int32_t) * 2);
948 connection_write(c
, &ok
, sizeof(int32_t));
950 if (request
== ESD_PROTO_STANDBY
)
951 ok
= pa_sink_suspend_all(c
->protocol
->core
, TRUE
, PA_SUSPEND_USER
) >= 0;
953 pa_assert(request
== ESD_PROTO_RESUME
);
954 ok
= pa_sink_suspend_all(c
->protocol
->core
, FALSE
, PA_SUSPEND_USER
) >= 0;
957 connection_write(c
, &ok
, sizeof(int32_t));
962 static int esd_proto_standby_mode(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
964 pa_sink
*sink
, *source
;
966 connection_assert_ref(c
);
970 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
971 if (pa_sink_get_state(sink
) == PA_SINK_SUSPENDED
)
972 mode
= ESM_ON_STANDBY
;
974 if ((source
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_source
, PA_NAMEREG_SOURCE
)))
975 if (pa_source_get_state(source
) == PA_SOURCE_SUSPENDED
)
976 mode
= ESM_ON_STANDBY
;
978 mode
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, mode
);
980 connection_write(c
, &mode
, sizeof(mode
));
984 /*** client callbacks ***/
986 static void client_kill_cb(pa_client
*c
) {
989 connection_unlink(CONNECTION(c
->userdata
));
992 /*** pa_iochannel callbacks ***/
994 static int do_read(connection
*c
) {
995 connection_assert_ref(c
);
997 /* pa_log("READ"); */
999 if (c
->state
== ESD_NEXT_REQUEST
) {
1001 pa_assert(c
->read_data_length
< sizeof(c
->request
));
1003 if ((r
= pa_iochannel_read(c
->io
,
1004 ((uint8_t*) &c
->request
) + c
->read_data_length
,
1005 sizeof(c
->request
) - c
->read_data_length
)) <= 0) {
1007 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1010 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1014 c
->read_data_length
+= (size_t) r
;
1016 if (c
->read_data_length
>= sizeof(c
->request
)) {
1017 struct proto_handler
*handler
;
1019 c
->request
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, c
->request
);
1021 if (c
->request
< ESD_PROTO_CONNECT
|| c
->request
>= ESD_PROTO_MAX
) {
1022 pa_log("recieved invalid request.");
1026 handler
= proto_map
+c
->request
;
1028 /* pa_log("executing request #%u", c->request); */
1030 if (!handler
->proc
) {
1031 pa_log("recieved unimplemented request #%u.", c
->request
);
1035 if (handler
->data_length
== 0) {
1036 c
->read_data_length
= 0;
1038 if (handler
->proc(c
, c
->request
, NULL
, 0) < 0)
1042 if (c
->read_data_alloc
< handler
->data_length
)
1043 c
->read_data
= pa_xrealloc(c
->read_data
, c
->read_data_alloc
= handler
->data_length
);
1044 pa_assert(c
->read_data
);
1046 c
->state
= ESD_NEEDS_REQDATA
;
1047 c
->read_data_length
= 0;
1051 } else if (c
->state
== ESD_NEEDS_REQDATA
) {
1053 struct proto_handler
*handler
= proto_map
+c
->request
;
1055 pa_assert(handler
->proc
);
1057 pa_assert(c
->read_data
&& c
->read_data_length
< handler
->data_length
);
1059 if ((r
= pa_iochannel_read(c
->io
,
1060 (uint8_t*) c
->read_data
+ c
->read_data_length
,
1061 handler
->data_length
- c
->read_data_length
)) <= 0) {
1063 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1066 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1070 c
->read_data_length
+= (size_t) r
;
1071 if (c
->read_data_length
>= handler
->data_length
) {
1072 size_t l
= c
->read_data_length
;
1073 pa_assert(handler
->proc
);
1075 c
->state
= ESD_NEXT_REQUEST
;
1076 c
->read_data_length
= 0;
1078 if (handler
->proc(c
, c
->request
, c
->read_data
, l
) < 0)
1081 } else if (c
->state
== ESD_CACHING_SAMPLE
) {
1085 pa_assert(c
->scache
.memchunk
.memblock
);
1086 pa_assert(c
->scache
.name
);
1087 pa_assert(c
->scache
.memchunk
.index
< c
->scache
.memchunk
.length
);
1089 p
= pa_memblock_acquire(c
->scache
.memchunk
.memblock
);
1090 r
= pa_iochannel_read(c
->io
, (uint8_t*) p
+c
->scache
.memchunk
.index
, c
->scache
.memchunk
.length
-c
->scache
.memchunk
.index
);
1091 pa_memblock_release(c
->scache
.memchunk
.memblock
);
1094 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1097 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1101 c
->scache
.memchunk
.index
+= (size_t) r
;
1102 pa_assert(c
->scache
.memchunk
.index
<= c
->scache
.memchunk
.length
);
1104 if (c
->scache
.memchunk
.index
== c
->scache
.memchunk
.length
) {
1107 c
->scache
.memchunk
.index
= 0;
1108 pa_scache_add_item(c
->protocol
->core
, c
->scache
.name
, &c
->scache
.sample_spec
, NULL
, &c
->scache
.memchunk
, c
->client
->proplist
, &idx
);
1110 pa_memblock_unref(c
->scache
.memchunk
.memblock
);
1111 pa_memchunk_reset(&c
->scache
.memchunk
);
1113 pa_xfree(c
->scache
.name
);
1114 c
->scache
.name
= NULL
;
1116 c
->state
= ESD_NEXT_REQUEST
;
1119 connection_write(c
, &idx
, sizeof(uint32_t));
1122 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
1129 pa_assert(c
->input_memblockq
);
1131 /* pa_log("STREAMING_DATA"); */
1133 if (!(l
= (size_t) pa_atomic_load(&c
->playback
.missing
)))
1136 if (c
->playback
.current_memblock
) {
1138 space
= pa_memblock_get_length(c
->playback
.current_memblock
) - c
->playback
.memblock_index
;
1141 pa_memblock_unref(c
->playback
.current_memblock
);
1142 c
->playback
.current_memblock
= NULL
;
1146 if (!c
->playback
.current_memblock
) {
1147 pa_assert_se(c
->playback
.current_memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, (size_t) -1));
1148 c
->playback
.memblock_index
= 0;
1150 space
= pa_memblock_get_length(c
->playback
.current_memblock
);
1156 p
= pa_memblock_acquire(c
->playback
.current_memblock
);
1157 r
= pa_iochannel_read(c
->io
, (uint8_t*) p
+c
->playback
.memblock_index
, l
);
1158 pa_memblock_release(c
->playback
.current_memblock
);
1162 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1165 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1169 chunk
.memblock
= c
->playback
.current_memblock
;
1170 chunk
.index
= c
->playback
.memblock_index
;
1171 chunk
.length
= (size_t) r
;
1173 c
->playback
.memblock_index
+= (size_t) r
;
1175 pa_asyncmsgq_post(c
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(c
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, &chunk
, NULL
);
1176 pa_atomic_sub(&c
->playback
.missing
, (int) r
);
1182 static int do_write(connection
*c
) {
1183 connection_assert_ref(c
);
1185 /* pa_log("WRITE"); */
1187 if (c
->write_data_length
) {
1190 pa_assert(c
->write_data_index
< c
->write_data_length
);
1191 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) {
1193 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1196 pa_log("write(): %s", pa_cstrerror(errno
));
1200 c
->write_data_index
+= (size_t) r
;
1201 if (c
->write_data_index
>= c
->write_data_length
)
1202 c
->write_data_length
= c
->write_data_index
= 0;
1204 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->source_output
) {
1209 if (pa_memblockq_peek(c
->output_memblockq
, &chunk
) < 0)
1212 pa_assert(chunk
.memblock
);
1213 pa_assert(chunk
.length
);
1215 p
= pa_memblock_acquire(chunk
.memblock
);
1216 r
= pa_iochannel_write(c
->io
, (uint8_t*) p
+chunk
.index
, chunk
.length
);
1217 pa_memblock_release(chunk
.memblock
);
1219 pa_memblock_unref(chunk
.memblock
);
1223 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1226 pa_log("write(): %s", pa_cstrerror(errno
));
1230 pa_memblockq_drop(c
->output_memblockq
, (size_t) r
);
1236 static void do_work(connection
*c
) {
1237 connection_assert_ref(c
);
1239 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
1244 if (pa_iochannel_is_readable(c
->io
))
1248 if (c
->state
== ESD_STREAMING_DATA
&& !c
->sink_input
&& pa_iochannel_is_hungup(c
->io
))
1249 /* In case we are in capture mode we will never call read()
1250 * on the socket, hence we need to detect the hangup manually
1251 * here, instead of simply waiting for read() to return 0. */
1254 if (pa_iochannel_is_writable(c
->io
))
1255 if (do_write(c
) < 0)
1262 if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
1265 pa_iochannel_free(c
->io
);
1268 pa_asyncmsgq_post(c
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(c
->sink_input
), SINK_INPUT_MESSAGE_DISABLE_PREBUF
, NULL
, 0, NULL
, NULL
);
1270 connection_unlink(c
);
1273 static void io_callback(pa_iochannel
*io
, void *userdata
) {
1274 connection
*c
= CONNECTION(userdata
);
1276 connection_assert_ref(c
);
1282 static void defer_callback(pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
) {
1283 connection
*c
= CONNECTION(userdata
);
1285 connection_assert_ref(c
);
1291 static int connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1292 connection
*c
= CONNECTION(o
);
1293 connection_assert_ref(c
);
1299 case CONNECTION_MESSAGE_REQUEST_DATA
:
1303 case CONNECTION_MESSAGE_POST_DATA
:
1304 /* pa_log("got data %u", chunk->length); */
1305 pa_memblockq_push_align(c
->output_memblockq
, chunk
);
1309 case CONNECTION_MESSAGE_UNLINK_CONNECTION
:
1310 connection_unlink(c
);
1317 /*** sink_input callbacks ***/
1319 /* Called from thread context */
1320 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1321 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1324 pa_sink_input_assert_ref(i
);
1325 c
= CONNECTION(i
->userdata
);
1326 connection_assert_ref(c
);
1330 case SINK_INPUT_MESSAGE_POST_DATA
: {
1333 /* New data from the main loop */
1334 pa_memblockq_push_align(c
->input_memblockq
, chunk
);
1336 if (pa_memblockq_is_readable(c
->input_memblockq
) && c
->playback
.underrun
) {
1337 pa_log_debug("Requesting rewind due to end of underrun.");
1338 pa_sink_input_request_rewind(c
->sink_input
, 0, FALSE
, TRUE
, FALSE
);
1341 /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
1346 case SINK_INPUT_MESSAGE_DISABLE_PREBUF
:
1347 pa_memblockq_prebuf_disable(c
->input_memblockq
);
1350 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1351 pa_usec_t
*r
= userdata
;
1353 *r
= pa_bytes_to_usec(pa_memblockq_get_length(c
->input_memblockq
), &c
->sink_input
->sample_spec
);
1355 /* Fall through, the default handler will add in the extra
1356 * latency added by the resampler */
1360 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1364 /* Called from thread context */
1365 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
) {
1368 pa_sink_input_assert_ref(i
);
1369 c
= CONNECTION(i
->userdata
);
1370 connection_assert_ref(c
);
1373 if (pa_memblockq_peek(c
->input_memblockq
, chunk
) < 0) {
1375 c
->playback
.underrun
= TRUE
;
1377 if (c
->dead
&& pa_sink_input_safe_to_remove(i
))
1378 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_UNLINK_CONNECTION
, NULL
, 0, NULL
, NULL
);
1384 chunk
->length
= PA_MIN(length
, chunk
->length
);
1386 c
->playback
.underrun
= FALSE
;
1388 pa_memblockq_drop(c
->input_memblockq
, chunk
->length
);
1389 m
= pa_memblockq_pop_missing(c
->input_memblockq
);
1392 if (pa_atomic_add(&c
->playback
.missing
, (int) m
) <= 0)
1393 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1399 /* Called from thread context */
1400 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1403 pa_sink_input_assert_ref(i
);
1404 c
= CONNECTION(i
->userdata
);
1405 connection_assert_ref(c
);
1407 /* If we are in an underrun, then we don't rewind */
1408 if (i
->thread_info
.underrun_for
> 0)
1411 pa_memblockq_rewind(c
->input_memblockq
, nbytes
);
1414 /* Called from thread context */
1415 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1418 pa_sink_input_assert_ref(i
);
1419 c
= CONNECTION(i
->userdata
);
1420 connection_assert_ref(c
);
1422 pa_memblockq_set_maxrewind(c
->input_memblockq
, nbytes
);
1425 static void sink_input_kill_cb(pa_sink_input
*i
) {
1426 pa_sink_input_assert_ref(i
);
1428 connection_unlink(CONNECTION(i
->userdata
));
1431 /*** source_output callbacks ***/
1433 /* Called from thread context */
1434 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1437 pa_source_output_assert_ref(o
);
1438 c
= CONNECTION(o
->userdata
);
1442 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1445 static void source_output_kill_cb(pa_source_output
*o
) {
1446 pa_source_output_assert_ref(o
);
1448 connection_unlink(CONNECTION(o
->userdata
));
1451 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1454 pa_source_output_assert_ref(o
);
1455 c
= CONNECTION(o
->userdata
);
1458 return pa_bytes_to_usec(pa_memblockq_get_length(c
->output_memblockq
), &c
->source_output
->sample_spec
);
1461 /*** entry points ***/
1463 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
1464 connection
*c
= CONNECTION(userdata
);
1467 connection_assert_ref(c
);
1468 pa_assert(c
->auth_timeout_event
== e
);
1471 connection_unlink(c
);
1474 void pa_esound_protocol_connect(pa_esound_protocol
*p
, pa_iochannel
*io
, pa_esound_options
*o
) {
1477 pa_client_new_data data
;
1484 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
1485 pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
1486 pa_iochannel_free(io
);
1490 pa_client_new_data_init(&data
);
1491 data
.module
= o
->module
;
1492 data
.driver
= __FILE__
;
1493 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
1494 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "EsounD client (%s)", pname
);
1495 pa_proplist_sets(data
.proplist
, "esound-protocol.peer", pname
);
1496 client
= pa_client_new(p
->core
, &data
);
1497 pa_client_new_data_done(&data
);
1502 c
= pa_msgobject_new(connection
);
1503 c
->parent
.parent
.free
= connection_free
;
1504 c
->parent
.process_msg
= connection_process_msg
;
1507 pa_iochannel_set_callback(c
->io
, io_callback
, c
);
1510 c
->client
->kill
= client_kill_cb
;
1511 c
->client
->userdata
= c
;
1513 c
->options
= pa_esound_options_ref(o
);
1514 c
->authorized
= FALSE
;
1515 c
->swap_byte_order
= FALSE
;
1518 c
->read_data_length
= 0;
1519 c
->read_data
= pa_xmalloc(c
->read_data_alloc
= proto_map
[ESD_PROTO_CONNECT
].data_length
);
1521 c
->write_data_length
= c
->write_data_index
= c
->write_data_alloc
= 0;
1522 c
->write_data
= NULL
;
1524 c
->state
= ESD_NEEDS_REQDATA
;
1525 c
->request
= ESD_PROTO_CONNECT
;
1527 c
->sink_input
= NULL
;
1528 c
->input_memblockq
= NULL
;
1530 c
->source_output
= NULL
;
1531 c
->output_memblockq
= NULL
;
1533 c
->playback
.current_memblock
= NULL
;
1534 c
->playback
.memblock_index
= 0;
1535 c
->playback
.underrun
= TRUE
;
1536 pa_atomic_store(&c
->playback
.missing
, 0);
1538 pa_memchunk_reset(&c
->scache
.memchunk
);
1539 c
->scache
.name
= NULL
;
1541 c
->original_name
= NULL
;
1543 if (o
->auth_anonymous
) {
1544 pa_log_info("Client authenticated anonymously.");
1545 c
->authorized
= TRUE
;
1548 if (!c
->authorized
&&
1550 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
1552 pa_log_info("Client authenticated by IP ACL.");
1553 c
->authorized
= TRUE
;
1557 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
1559 c
->auth_timeout_event
= NULL
;
1561 c
->defer_event
= p
->core
->mainloop
->defer_new(p
->core
->mainloop
, defer_callback
, c
);
1562 p
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
1564 pa_idxset_put(p
->connections
, c
, &c
->index
);
1567 void pa_esound_protocol_disconnect(pa_esound_protocol
*p
, pa_module
*m
) {
1574 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
1575 if (c
->options
->module
== m
)
1576 connection_unlink(c
);
1579 static pa_esound_protocol
* esound_protocol_new(pa_core
*c
) {
1580 pa_esound_protocol
*p
;
1584 p
= pa_xnew(pa_esound_protocol
, 1);
1587 p
->connections
= pa_idxset_new(NULL
, NULL
);
1590 pa_assert_se(pa_shared_set(c
, "esound-protocol", p
) >= 0);
1595 pa_esound_protocol
* pa_esound_protocol_get(pa_core
*c
) {
1596 pa_esound_protocol
*p
;
1598 if ((p
= pa_shared_get(c
, "esound-protocol")))
1599 return pa_esound_protocol_ref(p
);
1601 return esound_protocol_new(c
);
1604 pa_esound_protocol
* pa_esound_protocol_ref(pa_esound_protocol
*p
) {
1606 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
1613 void pa_esound_protocol_unref(pa_esound_protocol
*p
) {
1616 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
1618 if (PA_REFCNT_DEC(p
) > 0)
1621 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
1622 connection_unlink(c
);
1624 pa_idxset_free(p
->connections
, NULL
, NULL
);
1626 pa_assert_se(pa_shared_remove(p
->core
, "esound-protocol") >= 0);
1631 pa_esound_options
* pa_esound_options_new(void) {
1632 pa_esound_options
*o
;
1634 o
= pa_xnew0(pa_esound_options
, 1);
1640 pa_esound_options
* pa_esound_options_ref(pa_esound_options
*o
) {
1642 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1649 void pa_esound_options_unref(pa_esound_options
*o
) {
1651 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1653 if (PA_REFCNT_DEC(o
) > 0)
1657 pa_ip_acl_free(o
->auth_ip_acl
);
1660 pa_auth_cookie_unref(o
->auth_cookie
);
1662 pa_xfree(o
->default_sink
);
1663 pa_xfree(o
->default_source
);
1668 int pa_esound_options_parse(pa_esound_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
1673 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1676 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
1677 pa_log("auth-anonymous= expects a boolean argument.");
1681 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
1684 if (!(ipa
= pa_ip_acl_new(acl
))) {
1685 pa_log("Failed to parse IP ACL '%s'", acl
);
1690 pa_ip_acl_free(o
->auth_ip_acl
);
1692 o
->auth_ip_acl
= ipa
;
1696 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
1697 pa_log("auth-cookie-enabled= expects a boolean argument.");
1702 pa_auth_cookie_unref(o
->auth_cookie
);
1707 /* The new name for this is 'auth-cookie', for compat reasons
1708 * we check the old name too */
1709 if (!(cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
)))
1710 if (!(cn
= pa_modargs_get_value(ma
, "cookie", NULL
)))
1711 cn
= DEFAULT_COOKIE_FILE
;
1713 if (!(o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, ESD_KEY_LEN
)))
1717 o
->auth_cookie
= NULL
;
1719 pa_xfree(o
->default_sink
);
1720 o
->default_sink
= pa_xstrdup(pa_modargs_get_value(ma
, "sink", NULL
));
1722 pa_xfree(o
->default_source
);
1723 o
->default_source
= pa_xstrdup(pa_modargs_get_value(ma
, "source", NULL
));