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>
58 #include <pulsecore/endianmacros.h>
60 #include "protocol-esound.h"
62 /* Don't accept more connection than this */
63 #define MAX_CONNECTIONS 64
65 /* Kick a client if it doesn't authenticate within this time */
66 #define AUTH_TIMEOUT (5*PA_USEC_PER_SEC)
68 #define DEFAULT_COOKIE_FILE ".esd_auth"
70 #define PLAYBACK_BUFFER_SECONDS (.25)
71 #define PLAYBACK_BUFFER_FRAGMENTS (10)
72 #define RECORD_BUFFER_SECONDS (5)
74 #define MAX_CACHE_SAMPLE_SIZE (2048000)
76 #define DEFAULT_SINK_LATENCY (150*PA_USEC_PER_MSEC)
77 #define DEFAULT_SOURCE_LATENCY (150*PA_USEC_PER_MSEC)
79 #define SCACHE_PREFIX "esound."
81 /* This is heavily based on esound's code */
83 typedef struct connection
{
88 pa_esound_protocol
*protocol
;
89 pa_esound_options
*options
;
92 pa_bool_t authorized
, swap_byte_order
;
94 size_t write_data_alloc
, write_data_index
, write_data_length
;
96 size_t read_data_alloc
, read_data_length
;
98 esd_client_state_t state
;
99 pa_sink_input
*sink_input
;
100 pa_source_output
*source_output
;
101 pa_memblockq
*input_memblockq
, *output_memblockq
;
102 pa_defer_event
*defer_event
;
107 pa_memblock
*current_memblock
;
108 size_t memblock_index
;
114 pa_memchunk memchunk
;
116 pa_sample_spec sample_spec
;
119 pa_time_event
*auth_timeout_event
;
122 PA_DEFINE_PRIVATE_CLASS(connection
, pa_msgobject
);
123 #define CONNECTION(o) (connection_cast(o))
125 struct pa_esound_protocol
{
129 pa_idxset
*connections
;
134 SINK_INPUT_MESSAGE_POST_DATA
= PA_SINK_INPUT_MESSAGE_MAX
, /* data from main loop to sink input */
135 SINK_INPUT_MESSAGE_DISABLE_PREBUF
139 CONNECTION_MESSAGE_REQUEST_DATA
,
140 CONNECTION_MESSAGE_POST_DATA
,
141 CONNECTION_MESSAGE_UNLINK_CONNECTION
144 typedef struct proto_handler
{
146 int (*proc
)(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
147 const char *description
;
148 } esd_proto_handler_info_t
;
150 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
);
151 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
152 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
153 static void sink_input_kill_cb(pa_sink_input
*i
);
154 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
155 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
157 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
158 static void source_output_kill_cb(pa_source_output
*o
);
160 static int esd_proto_connect(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
161 static int esd_proto_stream_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
162 static int esd_proto_stream_record(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
163 static int esd_proto_get_latency(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
164 static int esd_proto_server_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
165 static int esd_proto_all_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
166 static int esd_proto_stream_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
167 static int esd_proto_sample_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
168 static int esd_proto_sample_cache(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
169 static int esd_proto_sample_free_or_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
170 static int esd_proto_sample_get_id(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
171 static int esd_proto_standby_or_resume(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
172 static int esd_proto_standby_mode(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
174 /* the big map of protocol handler info */
175 static struct proto_handler proto_map
[ESD_PROTO_MAX
] = {
176 { ESD_KEY_LEN
+ sizeof(int), esd_proto_connect
, "connect" },
177 { ESD_KEY_LEN
+ sizeof(int), NULL
, "lock" },
178 { ESD_KEY_LEN
+ sizeof(int), NULL
, "unlock" },
180 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_play
, "stream play" },
181 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream rec" },
182 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream mon" },
184 { ESD_NAME_MAX
+ 3 * sizeof(int), esd_proto_sample_cache
, "sample cache" }, /* 6 */
185 { sizeof(int), esd_proto_sample_free_or_play
, "sample free" },
186 { sizeof(int), esd_proto_sample_free_or_play
, "sample play" }, /* 8 */
187 { sizeof(int), NULL
, "sample loop" },
188 { sizeof(int), NULL
, "sample stop" },
189 { (size_t) -1, NULL
, "TODO: sample kill" },
191 { ESD_KEY_LEN
+ sizeof(int), esd_proto_standby_or_resume
, "standby" },
192 { ESD_KEY_LEN
+ sizeof(int), esd_proto_standby_or_resume
, "resume" }, /* 13 */
194 { ESD_NAME_MAX
, esd_proto_sample_get_id
, "sample getid" }, /* 14 */
195 { ESD_NAME_MAX
+ 2 * sizeof(int), NULL
, "stream filter" },
197 { sizeof(int), esd_proto_server_info
, "server info" },
198 { sizeof(int), esd_proto_all_info
, "all info" },
199 { (size_t) -1, NULL
, "TODO: subscribe" },
200 { (size_t) -1, NULL
, "TODO: unsubscribe" },
202 { 3 * sizeof(int), esd_proto_stream_pan
, "stream pan"},
203 { 3 * sizeof(int), esd_proto_sample_pan
, "sample pan" },
205 { sizeof(int), esd_proto_standby_mode
, "standby mode" },
206 { 0, esd_proto_get_latency
, "get latency" }
209 static void connection_unlink(connection
*c
) {
216 pa_esound_options_unref(c
->options
);
221 pa_sink_input_unlink(c
->sink_input
);
222 pa_sink_input_unref(c
->sink_input
);
223 c
->sink_input
= NULL
;
226 if (c
->source_output
) {
227 pa_source_output_unlink(c
->source_output
);
228 pa_source_output_unref(c
->source_output
);
229 c
->source_output
= NULL
;
233 pa_client_free(c
->client
);
237 if (c
->state
== ESD_STREAMING_DATA
)
238 c
->protocol
->n_player
--;
241 pa_iochannel_free(c
->io
);
245 if (c
->defer_event
) {
246 c
->protocol
->core
->mainloop
->defer_free(c
->defer_event
);
247 c
->defer_event
= NULL
;
250 if (c
->auth_timeout_event
) {
251 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
252 c
->auth_timeout_event
= NULL
;
255 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
260 static void connection_free(pa_object
*obj
) {
261 connection
*c
= CONNECTION(obj
);
264 if (c
->input_memblockq
)
265 pa_memblockq_free(c
->input_memblockq
);
266 if (c
->output_memblockq
)
267 pa_memblockq_free(c
->output_memblockq
);
269 if (c
->playback
.current_memblock
)
270 pa_memblock_unref(c
->playback
.current_memblock
);
272 pa_xfree(c
->read_data
);
273 pa_xfree(c
->write_data
);
275 if (c
->scache
.memchunk
.memblock
)
276 pa_memblock_unref(c
->scache
.memchunk
.memblock
);
277 pa_xfree(c
->scache
.name
);
279 pa_xfree(c
->original_name
);
283 static void connection_write_prepare(connection
*c
, size_t length
) {
287 t
= c
->write_data_length
+length
;
289 if (c
->write_data_alloc
< t
)
290 c
->write_data
= pa_xrealloc(c
->write_data
, c
->write_data_alloc
= t
);
292 pa_assert(c
->write_data
);
295 static void connection_write(connection
*c
, const void *data
, size_t length
) {
299 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
301 connection_write_prepare(c
, length
);
303 pa_assert(c
->write_data
);
305 i
= c
->write_data_length
;
306 c
->write_data_length
+= length
;
308 memcpy((uint8_t*) c
->write_data
+ i
, data
, length
);
311 static void format_esd2native(int format
, pa_bool_t swap_bytes
, pa_sample_spec
*ss
) {
314 ss
->channels
= (uint8_t) (((format
& ESD_MASK_CHAN
) == ESD_STEREO
) ? 2 : 1);
315 if ((format
& ESD_MASK_BITS
) == ESD_BITS16
)
316 ss
->format
= swap_bytes
? PA_SAMPLE_S16RE
: PA_SAMPLE_S16NE
;
318 ss
->format
= PA_SAMPLE_U8
;
321 static int format_native2esd(pa_sample_spec
*ss
) {
324 format
= (ss
->format
== PA_SAMPLE_U8
) ? ESD_BITS8
: ESD_BITS16
;
325 format
|= (ss
->channels
>= 2) ? ESD_STEREO
: ESD_MONO
;
330 #define CHECK_VALIDITY(expression, ...) do { \
331 if (PA_UNLIKELY(!(expression))) { \
332 pa_log_warn(__FILE__ ": " __VA_ARGS__); \
337 /*** esound commands ***/
339 static int esd_proto_connect(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
343 connection_assert_ref(c
);
345 pa_assert(length
== (ESD_KEY_LEN
+ sizeof(uint32_t)));
347 if (!c
->authorized
&& c
->options
->auth_cookie
) {
350 if ((key
= pa_auth_cookie_read(c
->options
->auth_cookie
, ESD_KEY_LEN
)))
351 if (memcmp(data
, key
, ESD_KEY_LEN
) == 0)
352 c
->authorized
= TRUE
;
355 if (!c
->authorized
) {
356 pa_log("Kicked client with invalid authorization key.");
360 if (c
->auth_timeout_event
) {
361 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
362 c
->auth_timeout_event
= NULL
;
365 data
= (const char*)data
+ ESD_KEY_LEN
;
367 memcpy(&ekey
, data
, sizeof(uint32_t));
368 if (ekey
== ESD_ENDIAN_KEY
)
369 c
->swap_byte_order
= FALSE
;
370 else if (ekey
== ESD_SWAP_ENDIAN_KEY
)
371 c
->swap_byte_order
= TRUE
;
373 pa_log_warn("Client sent invalid endian key");
377 pa_proplist_sets(c
->client
->proplist
, "esound.byte_order", c
->swap_byte_order
? "reverse" : "native");
380 connection_write(c
, &ok
, sizeof(int));
384 static int esd_proto_stream_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
385 char name
[ESD_NAME_MAX
], *utf8_name
;
386 int32_t format
, rate
;
389 pa_sink
*sink
= NULL
;
390 pa_sink_input_new_data sdata
;
393 connection_assert_ref(c
);
395 pa_assert(length
== (sizeof(int32_t)*2+ESD_NAME_MAX
));
397 memcpy(&format
, data
, sizeof(int32_t));
398 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
399 data
= (const char*) data
+ sizeof(int32_t);
401 memcpy(&rate
, data
, sizeof(int32_t));
402 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
403 data
= (const char*) data
+ sizeof(int32_t);
405 ss
.rate
= (uint32_t) rate
;
406 format_esd2native(format
, c
->swap_byte_order
, &ss
);
408 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification");
410 if (c
->options
->default_sink
) {
411 sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
);
412 CHECK_VALIDITY(sink
, "No such sink: %s", pa_strnull(c
->options
->default_sink
));
415 pa_strlcpy(name
, data
, sizeof(name
));
417 utf8_name
= pa_utf8_filter(name
);
418 pa_client_set_name(c
->client
, utf8_name
);
421 c
->original_name
= pa_xstrdup(name
);
423 pa_assert(!c
->sink_input
&& !c
->input_memblockq
);
425 pa_sink_input_new_data_init(&sdata
);
426 sdata
.driver
= __FILE__
;
427 sdata
.module
= c
->options
->module
;
428 sdata
.client
= c
->client
;
429 pa_sink_input_new_data_set_sink(&sdata
, sink
, FALSE
);
430 pa_sink_input_new_data_set_sample_spec(&sdata
, &ss
);
432 pa_sink_input_new(&c
->sink_input
, c
->protocol
->core
, &sdata
);
433 pa_sink_input_new_data_done(&sdata
);
435 CHECK_VALIDITY(c
->sink_input
, "Failed to create sink input.");
437 l
= (size_t) ((double) pa_bytes_per_second(&ss
)*PLAYBACK_BUFFER_SECONDS
);
438 pa_sink_input_get_silence(c
->sink_input
, &silence
);
439 c
->input_memblockq
= pa_memblockq_new(
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
;
527 sdata
.source
= source
;
528 pa_source_output_new_data_set_sample_spec(&sdata
, &ss
);
530 pa_source_output_new(&c
->source_output
, c
->protocol
->core
, &sdata
);
531 pa_source_output_new_data_done(&sdata
);
533 CHECK_VALIDITY(c
->source_output
, "Failed to create source output.");
535 l
= (size_t) (pa_bytes_per_second(&ss
)*RECORD_BUFFER_SECONDS
);
536 c
->output_memblockq
= pa_memblockq_new(
545 pa_iochannel_socket_set_sndbuf(c
->io
, l
);
547 c
->source_output
->push
= source_output_push_cb
;
548 c
->source_output
->kill
= source_output_kill_cb
;
549 c
->source_output
->get_latency
= source_output_get_latency_cb
;
550 c
->source_output
->userdata
= c
;
552 pa_source_output_set_requested_latency(c
->source_output
, DEFAULT_SOURCE_LATENCY
);
554 c
->state
= ESD_STREAMING_DATA
;
556 c
->protocol
->n_player
++;
558 pa_source_output_put(c
->source_output
);
563 static int esd_proto_get_latency(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
567 connection_assert_ref(c
);
569 pa_assert(length
== 0);
571 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
574 double usec
= (double) pa_sink_get_requested_latency(sink
);
575 latency
= (int) ((usec
*44100)/1000000);
578 latency
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, latency
);
579 connection_write(c
, &latency
, sizeof(int32_t));
584 static int esd_proto_server_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
585 int32_t rate
= 44100, format
= ESD_STEREO
|ESD_BITS16
;
589 connection_assert_ref(c
);
591 pa_assert(length
== sizeof(int32_t));
593 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
))) {
594 rate
= (int32_t) sink
->sample_spec
.rate
;
595 format
= format_native2esd(&sink
->sample_spec
);
598 connection_write_prepare(c
, sizeof(int32_t) * 3);
601 connection_write(c
, &response
, sizeof(int32_t));
602 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
603 connection_write(c
, &rate
, sizeof(int32_t));
604 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
605 connection_write(c
, &format
, sizeof(int32_t));
610 static int esd_proto_all_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
613 uint32_t idx
= PA_IDXSET_INVALID
;
615 char terminator
[sizeof(int32_t)*6+ESD_NAME_MAX
];
617 connection_assert_ref(c
);
619 pa_assert(length
== sizeof(int32_t));
621 if (esd_proto_server_info(c
, request
, data
, length
) < 0)
624 k
= sizeof(int32_t)*5+ESD_NAME_MAX
;
625 s
= sizeof(int32_t)*6+ESD_NAME_MAX
;
626 nsamples
= pa_idxset_size(c
->protocol
->core
->scache
);
627 t
= s
*(nsamples
+1) + k
*(c
->protocol
->n_player
+1);
629 connection_write_prepare(c
, t
);
631 memset(terminator
, 0, sizeof(terminator
));
633 PA_IDXSET_FOREACH(conn
, c
->protocol
->connections
, idx
) {
634 int32_t id
, format
= ESD_BITS16
| ESD_STEREO
, rate
= 44100, lvolume
= ESD_VOLUME_BASE
, rvolume
= ESD_VOLUME_BASE
;
635 char name
[ESD_NAME_MAX
];
637 if (conn
->state
!= ESD_STREAMING_DATA
)
640 pa_assert(t
>= k
*2+s
);
642 if (conn
->sink_input
) {
644 pa_sink_input_get_volume(conn
->sink_input
, &volume
, TRUE
);
645 rate
= (int32_t) conn
->sink_input
->sample_spec
.rate
;
646 lvolume
= (int32_t) ((volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
647 rvolume
= (int32_t) ((volume
.values
[volume
.channels
== 2 ? 1 : 0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
648 format
= format_native2esd(&conn
->sink_input
->sample_spec
);
652 id
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) (conn
->index
+1));
653 connection_write(c
, &id
, sizeof(int32_t));
656 memset(name
, 0, ESD_NAME_MAX
); /* don't leak old data */
657 if (conn
->original_name
)
658 strncpy(name
, conn
->original_name
, ESD_NAME_MAX
);
659 else if (conn
->client
&& pa_proplist_gets(conn
->client
->proplist
, PA_PROP_APPLICATION_NAME
))
660 strncpy(name
, pa_proplist_gets(conn
->client
->proplist
, PA_PROP_APPLICATION_NAME
), ESD_NAME_MAX
);
661 connection_write(c
, name
, ESD_NAME_MAX
);
664 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
665 connection_write(c
, &rate
, sizeof(int32_t));
668 lvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, lvolume
);
669 connection_write(c
, &lvolume
, sizeof(int32_t));
672 rvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rvolume
);
673 connection_write(c
, &rvolume
, sizeof(int32_t));
676 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
677 connection_write(c
, &format
, sizeof(int32_t));
682 pa_assert(t
== s
*(nsamples
+1)+k
);
685 connection_write(c
, terminator
, k
);
690 idx
= PA_IDXSET_INVALID
;
692 PA_IDXSET_FOREACH(ce
, c
->protocol
->core
->scache
, idx
) {
693 int32_t id
, rate
, lvolume
, rvolume
, format
, len
;
694 char name
[ESD_NAME_MAX
];
695 pa_channel_map stereo
= { .channels
= 2, .map
= { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
} };
701 if (ce
->volume_is_set
) {
703 pa_cvolume_remap(&volume
, &ce
->channel_map
, &stereo
);
705 pa_cvolume_reset(&volume
, 2);
707 if (ce
->memchunk
.memblock
)
708 ss
= ce
->sample_spec
;
710 ss
.format
= PA_SAMPLE_S16NE
;
716 id
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) (ce
->index
+1));
717 connection_write(c
, &id
, sizeof(int32_t));
720 memset(name
, 0, ESD_NAME_MAX
); /* don't leak old data */
721 if (strncmp(ce
->name
, SCACHE_PREFIX
, sizeof(SCACHE_PREFIX
)-1) == 0)
722 strncpy(name
, ce
->name
+sizeof(SCACHE_PREFIX
)-1, ESD_NAME_MAX
);
724 pa_snprintf(name
, ESD_NAME_MAX
, "native.%s", ce
->name
);
725 connection_write(c
, name
, ESD_NAME_MAX
);
728 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ss
.rate
);
729 connection_write(c
, &rate
, sizeof(int32_t));
732 lvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ((volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
));
733 connection_write(c
, &lvolume
, sizeof(int32_t));
736 rvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ((volume
.values
[1]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
));
737 connection_write(c
, &rvolume
, sizeof(int32_t));
740 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format_native2esd(&ss
));
741 connection_write(c
, &format
, sizeof(int32_t));
744 len
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) ce
->memchunk
.length
);
745 connection_write(c
, &len
, sizeof(int32_t));
753 connection_write(c
, terminator
, s
);
758 static int esd_proto_stream_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
760 uint32_t idx
, lvolume
, rvolume
;
763 connection_assert_ref(c
);
765 pa_assert(length
== sizeof(int32_t)*3);
767 memcpy(&idx
, data
, sizeof(uint32_t));
768 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
769 data
= (const char*)data
+ sizeof(uint32_t);
771 memcpy(&lvolume
, data
, sizeof(uint32_t));
772 lvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
773 data
= (const char*)data
+ sizeof(uint32_t);
775 memcpy(&rvolume
, data
, sizeof(uint32_t));
776 rvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
778 if ((conn
= pa_idxset_get_by_index(c
->protocol
->connections
, idx
)) && conn
->sink_input
) {
780 volume
.values
[0] = (lvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
781 volume
.values
[1] = (rvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
782 volume
.channels
= conn
->sink_input
->sample_spec
.channels
;
784 pa_sink_input_set_volume(conn
->sink_input
, &volume
, TRUE
, TRUE
);
789 connection_write(c
, &ok
, sizeof(int32_t));
794 static int esd_proto_sample_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
796 uint32_t idx
, lvolume
, rvolume
;
800 connection_assert_ref(c
);
802 pa_assert(length
== sizeof(int32_t)*3);
804 memcpy(&idx
, data
, sizeof(uint32_t));
805 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
806 data
= (const char*)data
+ sizeof(uint32_t);
808 memcpy(&lvolume
, data
, sizeof(uint32_t));
809 lvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
810 data
= (const char*)data
+ sizeof(uint32_t);
812 memcpy(&rvolume
, data
, sizeof(uint32_t));
813 rvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
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
)) <= 0)
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_atomic_sub(&c
->playback
.missing
, (int) r
);
1176 pa_asyncmsgq_post(c
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(c
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, &chunk
, NULL
);
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 c
->playback
.underrun
= FALSE
;
1386 chunk
->length
= PA_MIN(length
, chunk
->length
);
1387 pa_memblockq_drop(c
->input_memblockq
, chunk
->length
);
1388 m
= pa_memblockq_pop_missing(c
->input_memblockq
);
1391 if (pa_atomic_add(&c
->playback
.missing
, (int) m
) <= 0)
1392 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1398 /* Called from thread context */
1399 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1402 pa_sink_input_assert_ref(i
);
1403 c
= CONNECTION(i
->userdata
);
1404 connection_assert_ref(c
);
1406 /* If we are in an underrun, then we don't rewind */
1407 if (i
->thread_info
.underrun_for
> 0)
1410 pa_memblockq_rewind(c
->input_memblockq
, nbytes
);
1413 /* Called from thread context */
1414 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1417 pa_sink_input_assert_ref(i
);
1418 c
= CONNECTION(i
->userdata
);
1419 connection_assert_ref(c
);
1421 pa_memblockq_set_maxrewind(c
->input_memblockq
, nbytes
);
1424 static void sink_input_kill_cb(pa_sink_input
*i
) {
1425 pa_sink_input_assert_ref(i
);
1427 connection_unlink(CONNECTION(i
->userdata
));
1430 /*** source_output callbacks ***/
1432 /* Called from thread context */
1433 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1436 pa_source_output_assert_ref(o
);
1437 c
= CONNECTION(o
->userdata
);
1441 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1444 static void source_output_kill_cb(pa_source_output
*o
) {
1445 pa_source_output_assert_ref(o
);
1447 connection_unlink(CONNECTION(o
->userdata
));
1450 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1453 pa_source_output_assert_ref(o
);
1454 c
= CONNECTION(o
->userdata
);
1457 return pa_bytes_to_usec(pa_memblockq_get_length(c
->output_memblockq
), &c
->source_output
->sample_spec
);
1460 /*** entry points ***/
1462 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
1463 connection
*c
= CONNECTION(userdata
);
1466 connection_assert_ref(c
);
1467 pa_assert(c
->auth_timeout_event
== e
);
1470 connection_unlink(c
);
1473 void pa_esound_protocol_connect(pa_esound_protocol
*p
, pa_iochannel
*io
, pa_esound_options
*o
) {
1476 pa_client_new_data data
;
1483 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
1484 pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
1485 pa_iochannel_free(io
);
1489 pa_client_new_data_init(&data
);
1490 data
.module
= o
->module
;
1491 data
.driver
= __FILE__
;
1492 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
1493 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "EsounD client (%s)", pname
);
1494 pa_proplist_sets(data
.proplist
, "esound-protocol.peer", pname
);
1495 client
= pa_client_new(p
->core
, &data
);
1496 pa_client_new_data_done(&data
);
1501 c
= pa_msgobject_new(connection
);
1502 c
->parent
.parent
.free
= connection_free
;
1503 c
->parent
.process_msg
= connection_process_msg
;
1506 pa_iochannel_set_callback(c
->io
, io_callback
, c
);
1509 c
->client
->kill
= client_kill_cb
;
1510 c
->client
->userdata
= c
;
1512 c
->options
= pa_esound_options_ref(o
);
1513 c
->authorized
= FALSE
;
1514 c
->swap_byte_order
= FALSE
;
1517 c
->read_data_length
= 0;
1518 c
->read_data
= pa_xmalloc(c
->read_data_alloc
= proto_map
[ESD_PROTO_CONNECT
].data_length
);
1520 c
->write_data_length
= c
->write_data_index
= c
->write_data_alloc
= 0;
1521 c
->write_data
= NULL
;
1523 c
->state
= ESD_NEEDS_REQDATA
;
1524 c
->request
= ESD_PROTO_CONNECT
;
1526 c
->sink_input
= NULL
;
1527 c
->input_memblockq
= NULL
;
1529 c
->source_output
= NULL
;
1530 c
->output_memblockq
= NULL
;
1532 c
->playback
.current_memblock
= NULL
;
1533 c
->playback
.memblock_index
= 0;
1534 c
->playback
.underrun
= TRUE
;
1535 pa_atomic_store(&c
->playback
.missing
, 0);
1537 pa_memchunk_reset(&c
->scache
.memchunk
);
1538 c
->scache
.name
= NULL
;
1540 c
->original_name
= NULL
;
1542 if (o
->auth_anonymous
) {
1543 pa_log_info("Client authenticated anonymously.");
1544 c
->authorized
= TRUE
;
1547 if (!c
->authorized
&&
1549 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
1551 pa_log_info("Client authenticated by IP ACL.");
1552 c
->authorized
= TRUE
;
1556 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
1558 c
->auth_timeout_event
= NULL
;
1560 c
->defer_event
= p
->core
->mainloop
->defer_new(p
->core
->mainloop
, defer_callback
, c
);
1561 p
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
1563 pa_idxset_put(p
->connections
, c
, &c
->index
);
1566 void pa_esound_protocol_disconnect(pa_esound_protocol
*p
, pa_module
*m
) {
1573 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
1574 if (c
->options
->module
== m
)
1575 connection_unlink(c
);
1578 static pa_esound_protocol
* esound_protocol_new(pa_core
*c
) {
1579 pa_esound_protocol
*p
;
1583 p
= pa_xnew(pa_esound_protocol
, 1);
1586 p
->connections
= pa_idxset_new(NULL
, NULL
);
1589 pa_assert_se(pa_shared_set(c
, "esound-protocol", p
) >= 0);
1594 pa_esound_protocol
* pa_esound_protocol_get(pa_core
*c
) {
1595 pa_esound_protocol
*p
;
1597 if ((p
= pa_shared_get(c
, "esound-protocol")))
1598 return pa_esound_protocol_ref(p
);
1600 return esound_protocol_new(c
);
1603 pa_esound_protocol
* pa_esound_protocol_ref(pa_esound_protocol
*p
) {
1605 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
1612 void pa_esound_protocol_unref(pa_esound_protocol
*p
) {
1615 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
1617 if (PA_REFCNT_DEC(p
) > 0)
1620 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
1621 connection_unlink(c
);
1623 pa_idxset_free(p
->connections
, NULL
, NULL
);
1625 pa_assert_se(pa_shared_remove(p
->core
, "esound-protocol") >= 0);
1630 pa_esound_options
* pa_esound_options_new(void) {
1631 pa_esound_options
*o
;
1633 o
= pa_xnew0(pa_esound_options
, 1);
1639 pa_esound_options
* pa_esound_options_ref(pa_esound_options
*o
) {
1641 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1648 void pa_esound_options_unref(pa_esound_options
*o
) {
1650 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1652 if (PA_REFCNT_DEC(o
) > 0)
1656 pa_ip_acl_free(o
->auth_ip_acl
);
1659 pa_auth_cookie_unref(o
->auth_cookie
);
1661 pa_xfree(o
->default_sink
);
1662 pa_xfree(o
->default_source
);
1667 int pa_esound_options_parse(pa_esound_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
1672 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1675 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
1676 pa_log("auth-anonymous= expects a boolean argument.");
1680 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
1683 if (!(ipa
= pa_ip_acl_new(acl
))) {
1684 pa_log("Failed to parse IP ACL '%s'", acl
);
1689 pa_ip_acl_free(o
->auth_ip_acl
);
1691 o
->auth_ip_acl
= ipa
;
1695 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
1696 pa_log("auth-cookie-enabled= expects a boolean argument.");
1701 pa_auth_cookie_unref(o
->auth_cookie
);
1706 /* The new name for this is 'auth-cookie', for compat reasons
1707 * we check the old name too */
1708 if (!(cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
)))
1709 if (!(cn
= pa_modargs_get_value(ma
, "cookie", NULL
)))
1710 cn
= DEFAULT_COOKIE_FILE
;
1712 if (!(o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, ESD_KEY_LEN
)))
1716 o
->auth_cookie
= NULL
;
1718 pa_xfree(o
->default_sink
);
1719 o
->default_sink
= pa_xstrdup(pa_modargs_get_value(ma
, "sink", NULL
));
1721 pa_xfree(o
->default_source
);
1722 o
->default_source
= pa_xstrdup(pa_modargs_get_value(ma
, "source", NULL
));