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
;
430 pa_sink_input_new_data_set_sink(&sdata
, sink
, FALSE
);
431 pa_sink_input_new_data_set_sample_spec(&sdata
, &ss
);
433 pa_sink_input_new(&c
->sink_input
, c
->protocol
->core
, &sdata
);
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 pa_sink_input_get_silence(c
->sink_input
, &silence
);
440 c
->input_memblockq
= pa_memblockq_new(
446 l
/PLAYBACK_BUFFER_FRAGMENTS
,
449 pa_memblock_unref(silence
.memblock
);
450 pa_iochannel_socket_set_rcvbuf(c
->io
, l
);
452 c
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
453 c
->sink_input
->pop
= sink_input_pop_cb
;
454 c
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
455 c
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
456 c
->sink_input
->kill
= sink_input_kill_cb
;
457 c
->sink_input
->userdata
= c
;
459 pa_sink_input_set_requested_latency(c
->sink_input
, DEFAULT_SINK_LATENCY
);
461 c
->state
= ESD_STREAMING_DATA
;
463 c
->protocol
->n_player
++;
465 pa_atomic_store(&c
->playback
.missing
, (int) pa_memblockq_pop_missing(c
->input_memblockq
));
467 pa_sink_input_put(c
->sink_input
);
472 static int esd_proto_stream_record(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
473 char name
[ESD_NAME_MAX
], *utf8_name
;
474 int32_t format
, rate
;
475 pa_source
*source
= NULL
;
478 pa_source_output_new_data sdata
;
480 connection_assert_ref(c
);
482 pa_assert(length
== (sizeof(int32_t)*2+ESD_NAME_MAX
));
484 memcpy(&format
, data
, sizeof(int32_t));
485 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
486 data
= (const char*) data
+ sizeof(int32_t);
488 memcpy(&rate
, data
, sizeof(int32_t));
489 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
490 data
= (const char*) data
+ sizeof(int32_t);
492 ss
.rate
= (uint32_t) rate
;
493 format_esd2native(format
, c
->swap_byte_order
, &ss
);
495 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification.");
497 if (request
== ESD_PROTO_STREAM_MON
) {
500 sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
);
501 CHECK_VALIDITY(sink
, "No such sink: %s", pa_strnull(c
->options
->default_sink
));
503 source
= sink
->monitor_source
;
504 CHECK_VALIDITY(source
, "No such source.");
506 pa_assert(request
== ESD_PROTO_STREAM_REC
);
508 if (c
->options
->default_source
) {
509 source
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_source
, PA_NAMEREG_SOURCE
);
510 CHECK_VALIDITY(source
, "No such source: %s", pa_strnull(c
->options
->default_source
));
514 pa_strlcpy(name
, data
, sizeof(name
));
516 utf8_name
= pa_utf8_filter(name
);
517 pa_client_set_name(c
->client
, utf8_name
);
520 c
->original_name
= pa_xstrdup(name
);
522 pa_assert(!c
->output_memblockq
&& !c
->source_output
);
524 pa_source_output_new_data_init(&sdata
);
525 sdata
.driver
= __FILE__
;
526 sdata
.module
= c
->options
->module
;
527 sdata
.client
= c
->client
;
529 pa_source_output_new_data_set_source(&sdata
, source
, FALSE
);
530 pa_source_output_new_data_set_sample_spec(&sdata
, &ss
);
532 pa_source_output_new(&c
->source_output
, c
->protocol
->core
, &sdata
);
533 pa_source_output_new_data_done(&sdata
);
535 CHECK_VALIDITY(c
->source_output
, "Failed to create source output.");
537 l
= (size_t) (pa_bytes_per_second(&ss
)*RECORD_BUFFER_SECONDS
);
538 c
->output_memblockq
= pa_memblockq_new(
547 pa_iochannel_socket_set_sndbuf(c
->io
, l
);
549 c
->source_output
->push
= source_output_push_cb
;
550 c
->source_output
->kill
= source_output_kill_cb
;
551 c
->source_output
->get_latency
= source_output_get_latency_cb
;
552 c
->source_output
->userdata
= c
;
554 pa_source_output_set_requested_latency(c
->source_output
, DEFAULT_SOURCE_LATENCY
);
556 c
->state
= ESD_STREAMING_DATA
;
558 c
->protocol
->n_player
++;
560 pa_source_output_put(c
->source_output
);
565 static int esd_proto_get_latency(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
569 connection_assert_ref(c
);
571 pa_assert(length
== 0);
573 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
576 double usec
= (double) pa_sink_get_requested_latency(sink
);
577 latency
= (int) ((usec
*44100)/1000000);
580 latency
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, latency
);
581 connection_write(c
, &latency
, sizeof(int32_t));
586 static int esd_proto_server_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
587 int32_t rate
= 44100, format
= ESD_STEREO
|ESD_BITS16
;
591 connection_assert_ref(c
);
593 pa_assert(length
== sizeof(int32_t));
595 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
))) {
596 rate
= (int32_t) sink
->sample_spec
.rate
;
597 format
= format_native2esd(&sink
->sample_spec
);
600 connection_write_prepare(c
, sizeof(int32_t) * 3);
603 connection_write(c
, &response
, sizeof(int32_t));
604 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
605 connection_write(c
, &rate
, sizeof(int32_t));
606 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
607 connection_write(c
, &format
, sizeof(int32_t));
612 static int esd_proto_all_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
615 uint32_t idx
= PA_IDXSET_INVALID
;
617 char terminator
[sizeof(int32_t)*6+ESD_NAME_MAX
];
619 connection_assert_ref(c
);
621 pa_assert(length
== sizeof(int32_t));
623 if (esd_proto_server_info(c
, request
, data
, length
) < 0)
626 k
= sizeof(int32_t)*5+ESD_NAME_MAX
;
627 s
= sizeof(int32_t)*6+ESD_NAME_MAX
;
628 nsamples
= pa_idxset_size(c
->protocol
->core
->scache
);
629 t
= s
*(nsamples
+1) + k
*(c
->protocol
->n_player
+1);
631 connection_write_prepare(c
, t
);
633 memset(terminator
, 0, sizeof(terminator
));
635 PA_IDXSET_FOREACH(conn
, c
->protocol
->connections
, idx
) {
636 int32_t id
, format
= ESD_BITS16
| ESD_STEREO
, rate
= 44100, lvolume
= ESD_VOLUME_BASE
, rvolume
= ESD_VOLUME_BASE
;
637 char name
[ESD_NAME_MAX
];
639 if (conn
->state
!= ESD_STREAMING_DATA
)
642 pa_assert(t
>= k
*2+s
);
644 if (conn
->sink_input
) {
646 pa_sink_input_get_volume(conn
->sink_input
, &volume
, TRUE
);
647 rate
= (int32_t) conn
->sink_input
->sample_spec
.rate
;
648 lvolume
= (int32_t) ((volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
649 rvolume
= (int32_t) ((volume
.values
[volume
.channels
== 2 ? 1 : 0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
650 format
= format_native2esd(&conn
->sink_input
->sample_spec
);
654 id
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) (conn
->index
+1));
655 connection_write(c
, &id
, sizeof(int32_t));
658 memset(name
, 0, ESD_NAME_MAX
); /* don't leak old data */
659 if (conn
->original_name
)
660 strncpy(name
, conn
->original_name
, ESD_NAME_MAX
);
661 else if (conn
->client
&& pa_proplist_gets(conn
->client
->proplist
, PA_PROP_APPLICATION_NAME
))
662 strncpy(name
, pa_proplist_gets(conn
->client
->proplist
, PA_PROP_APPLICATION_NAME
), ESD_NAME_MAX
);
663 connection_write(c
, name
, ESD_NAME_MAX
);
666 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
667 connection_write(c
, &rate
, sizeof(int32_t));
670 lvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, lvolume
);
671 connection_write(c
, &lvolume
, sizeof(int32_t));
674 rvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rvolume
);
675 connection_write(c
, &rvolume
, sizeof(int32_t));
678 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
679 connection_write(c
, &format
, sizeof(int32_t));
684 pa_assert(t
== s
*(nsamples
+1)+k
);
687 connection_write(c
, terminator
, k
);
692 idx
= PA_IDXSET_INVALID
;
694 PA_IDXSET_FOREACH(ce
, c
->protocol
->core
->scache
, idx
) {
695 int32_t id
, rate
, lvolume
, rvolume
, format
, len
;
696 char name
[ESD_NAME_MAX
];
697 pa_channel_map stereo
= { .channels
= 2, .map
= { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
} };
703 if (ce
->volume_is_set
) {
705 pa_cvolume_remap(&volume
, &ce
->channel_map
, &stereo
);
707 pa_cvolume_reset(&volume
, 2);
709 if (ce
->memchunk
.memblock
)
710 ss
= ce
->sample_spec
;
712 ss
.format
= PA_SAMPLE_S16NE
;
718 id
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) (ce
->index
+1));
719 connection_write(c
, &id
, sizeof(int32_t));
722 memset(name
, 0, ESD_NAME_MAX
); /* don't leak old data */
723 if (strncmp(ce
->name
, SCACHE_PREFIX
, sizeof(SCACHE_PREFIX
)-1) == 0)
724 strncpy(name
, ce
->name
+sizeof(SCACHE_PREFIX
)-1, ESD_NAME_MAX
);
726 pa_snprintf(name
, ESD_NAME_MAX
, "native.%s", ce
->name
);
727 connection_write(c
, name
, ESD_NAME_MAX
);
730 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ss
.rate
);
731 connection_write(c
, &rate
, sizeof(int32_t));
734 lvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ((volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
));
735 connection_write(c
, &lvolume
, sizeof(int32_t));
738 rvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ((volume
.values
[1]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
));
739 connection_write(c
, &rvolume
, sizeof(int32_t));
742 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format_native2esd(&ss
));
743 connection_write(c
, &format
, sizeof(int32_t));
746 len
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) ce
->memchunk
.length
);
747 connection_write(c
, &len
, sizeof(int32_t));
755 connection_write(c
, terminator
, s
);
760 static int esd_proto_stream_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
762 uint32_t idx
, lvolume
, rvolume
;
765 connection_assert_ref(c
);
767 pa_assert(length
== sizeof(int32_t)*3);
769 memcpy(&idx
, data
, sizeof(uint32_t));
770 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
771 data
= (const char*)data
+ sizeof(uint32_t);
773 memcpy(&lvolume
, data
, sizeof(uint32_t));
774 lvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
775 data
= (const char*)data
+ sizeof(uint32_t);
777 memcpy(&rvolume
, data
, sizeof(uint32_t));
778 rvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
780 if ((conn
= pa_idxset_get_by_index(c
->protocol
->connections
, idx
)) && conn
->sink_input
) {
782 volume
.values
[0] = (lvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
783 volume
.values
[1] = (rvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
784 volume
.channels
= conn
->sink_input
->sample_spec
.channels
;
786 pa_sink_input_set_volume(conn
->sink_input
, &volume
, TRUE
, TRUE
);
791 connection_write(c
, &ok
, sizeof(int32_t));
796 static int esd_proto_sample_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
798 uint32_t idx
, lvolume
, rvolume
;
802 connection_assert_ref(c
);
804 pa_assert(length
== sizeof(int32_t)*3);
806 memcpy(&idx
, data
, sizeof(uint32_t));
807 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
808 data
= (const char*)data
+ sizeof(uint32_t);
810 memcpy(&lvolume
, data
, sizeof(uint32_t));
811 lvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
812 data
= (const char*)data
+ sizeof(uint32_t);
814 memcpy(&rvolume
, data
, sizeof(uint32_t));
815 rvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
817 volume
.values
[0] = (lvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
818 volume
.values
[1] = (rvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
821 if ((ce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
))) {
822 pa_channel_map stereo
= { .channels
= 2, .map
= { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
} };
824 pa_cvolume_remap(&volume
, &stereo
, &ce
->channel_map
);
826 ce
->volume_is_set
= TRUE
;
830 connection_write(c
, &ok
, sizeof(int32_t));
835 static int esd_proto_sample_cache(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
837 int32_t format
, rate
, sc_length
;
839 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
841 connection_assert_ref(c
);
843 pa_assert(length
== (ESD_NAME_MAX
+3*sizeof(int32_t)));
845 memcpy(&format
, data
, sizeof(int32_t));
846 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
847 data
= (const char*)data
+ sizeof(int32_t);
849 memcpy(&rate
, data
, sizeof(int32_t));
850 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
851 data
= (const char*)data
+ sizeof(int32_t);
853 ss
.rate
= (uint32_t) rate
;
854 format_esd2native(format
, c
->swap_byte_order
, &ss
);
856 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification.");
858 memcpy(&sc_length
, data
, sizeof(int32_t));
859 sc_length
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, sc_length
);
860 data
= (const char*)data
+ sizeof(int32_t);
862 CHECK_VALIDITY(sc_length
<= MAX_CACHE_SAMPLE_SIZE
, "Sample too large (%d bytes).", (int)sc_length
);
864 strcpy(name
, SCACHE_PREFIX
);
865 pa_strlcpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
867 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in sample name.");
869 pa_assert(!c
->scache
.memchunk
.memblock
);
870 c
->scache
.memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, (size_t) sc_length
);
871 c
->scache
.memchunk
.index
= 0;
872 c
->scache
.memchunk
.length
= (size_t) sc_length
;
873 c
->scache
.sample_spec
= ss
;
874 pa_assert(!c
->scache
.name
);
875 c
->scache
.name
= pa_xstrdup(name
);
877 c
->state
= ESD_CACHING_SAMPLE
;
879 pa_scache_add_item(c
->protocol
->core
, c
->scache
.name
, NULL
, NULL
, NULL
, c
->client
->proplist
, &idx
);
882 connection_write(c
, &idx
, sizeof(uint32_t));
887 static int esd_proto_sample_get_id(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
890 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
892 connection_assert_ref(c
);
894 pa_assert(length
== ESD_NAME_MAX
);
896 strcpy(name
, SCACHE_PREFIX
);
897 pa_strlcpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
899 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in sample name.");
902 if ((idx
= pa_scache_get_id_by_name(c
->protocol
->core
, name
)) != PA_IDXSET_INVALID
)
903 ok
= (int32_t) idx
+ 1;
905 connection_write(c
, &ok
, sizeof(int32_t));
910 static int esd_proto_sample_free_or_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
915 connection_assert_ref(c
);
917 pa_assert(length
== sizeof(int32_t));
919 memcpy(&idx
, data
, sizeof(uint32_t));
920 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
924 if ((name
= pa_scache_get_name_by_id(c
->protocol
->core
, idx
))) {
925 if (request
== ESD_PROTO_SAMPLE_PLAY
) {
928 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
929 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, PA_VOLUME_NORM
, c
->client
->proplist
, NULL
) >= 0)
930 ok
= (int32_t) idx
+ 1;
932 pa_assert(request
== ESD_PROTO_SAMPLE_FREE
);
934 if (pa_scache_remove_item(c
->protocol
->core
, name
) >= 0)
935 ok
= (int32_t) idx
+ 1;
939 connection_write(c
, &ok
, sizeof(int32_t));
944 static int esd_proto_standby_or_resume(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
947 connection_assert_ref(c
);
949 connection_write_prepare(c
, sizeof(int32_t) * 2);
950 connection_write(c
, &ok
, sizeof(int32_t));
952 if (request
== ESD_PROTO_STANDBY
)
953 ok
= pa_sink_suspend_all(c
->protocol
->core
, TRUE
, PA_SUSPEND_USER
) >= 0;
955 pa_assert(request
== ESD_PROTO_RESUME
);
956 ok
= pa_sink_suspend_all(c
->protocol
->core
, FALSE
, PA_SUSPEND_USER
) >= 0;
959 connection_write(c
, &ok
, sizeof(int32_t));
964 static int esd_proto_standby_mode(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
966 pa_sink
*sink
, *source
;
968 connection_assert_ref(c
);
972 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
973 if (pa_sink_get_state(sink
) == PA_SINK_SUSPENDED
)
974 mode
= ESM_ON_STANDBY
;
976 if ((source
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_source
, PA_NAMEREG_SOURCE
)))
977 if (pa_source_get_state(source
) == PA_SOURCE_SUSPENDED
)
978 mode
= ESM_ON_STANDBY
;
980 mode
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, mode
);
982 connection_write(c
, &mode
, sizeof(mode
));
986 /*** client callbacks ***/
988 static void client_kill_cb(pa_client
*c
) {
991 connection_unlink(CONNECTION(c
->userdata
));
994 /*** pa_iochannel callbacks ***/
996 static int do_read(connection
*c
) {
997 connection_assert_ref(c
);
999 /* pa_log("READ"); */
1001 if (c
->state
== ESD_NEXT_REQUEST
) {
1003 pa_assert(c
->read_data_length
< sizeof(c
->request
));
1005 if ((r
= pa_iochannel_read(c
->io
,
1006 ((uint8_t*) &c
->request
) + c
->read_data_length
,
1007 sizeof(c
->request
) - c
->read_data_length
)) <= 0) {
1009 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1012 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1016 c
->read_data_length
+= (size_t) r
;
1018 if (c
->read_data_length
>= sizeof(c
->request
)) {
1019 struct proto_handler
*handler
;
1021 c
->request
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, c
->request
);
1023 if (c
->request
< ESD_PROTO_CONNECT
|| c
->request
>= ESD_PROTO_MAX
) {
1024 pa_log("recieved invalid request.");
1028 handler
= proto_map
+c
->request
;
1030 /* pa_log("executing request #%u", c->request); */
1032 if (!handler
->proc
) {
1033 pa_log("recieved unimplemented request #%u.", c
->request
);
1037 if (handler
->data_length
== 0) {
1038 c
->read_data_length
= 0;
1040 if (handler
->proc(c
, c
->request
, NULL
, 0) < 0)
1044 if (c
->read_data_alloc
< handler
->data_length
)
1045 c
->read_data
= pa_xrealloc(c
->read_data
, c
->read_data_alloc
= handler
->data_length
);
1046 pa_assert(c
->read_data
);
1048 c
->state
= ESD_NEEDS_REQDATA
;
1049 c
->read_data_length
= 0;
1053 } else if (c
->state
== ESD_NEEDS_REQDATA
) {
1055 struct proto_handler
*handler
= proto_map
+c
->request
;
1057 pa_assert(handler
->proc
);
1059 pa_assert(c
->read_data
&& c
->read_data_length
< handler
->data_length
);
1061 if ((r
= pa_iochannel_read(c
->io
,
1062 (uint8_t*) c
->read_data
+ c
->read_data_length
,
1063 handler
->data_length
- c
->read_data_length
)) <= 0) {
1065 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1068 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1072 c
->read_data_length
+= (size_t) r
;
1073 if (c
->read_data_length
>= handler
->data_length
) {
1074 size_t l
= c
->read_data_length
;
1075 pa_assert(handler
->proc
);
1077 c
->state
= ESD_NEXT_REQUEST
;
1078 c
->read_data_length
= 0;
1080 if (handler
->proc(c
, c
->request
, c
->read_data
, l
) < 0)
1083 } else if (c
->state
== ESD_CACHING_SAMPLE
) {
1087 pa_assert(c
->scache
.memchunk
.memblock
);
1088 pa_assert(c
->scache
.name
);
1089 pa_assert(c
->scache
.memchunk
.index
< c
->scache
.memchunk
.length
);
1091 p
= pa_memblock_acquire(c
->scache
.memchunk
.memblock
);
1092 r
= pa_iochannel_read(c
->io
, (uint8_t*) p
+c
->scache
.memchunk
.index
, c
->scache
.memchunk
.length
-c
->scache
.memchunk
.index
);
1093 pa_memblock_release(c
->scache
.memchunk
.memblock
);
1096 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1099 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1103 c
->scache
.memchunk
.index
+= (size_t) r
;
1104 pa_assert(c
->scache
.memchunk
.index
<= c
->scache
.memchunk
.length
);
1106 if (c
->scache
.memchunk
.index
== c
->scache
.memchunk
.length
) {
1109 c
->scache
.memchunk
.index
= 0;
1110 pa_scache_add_item(c
->protocol
->core
, c
->scache
.name
, &c
->scache
.sample_spec
, NULL
, &c
->scache
.memchunk
, c
->client
->proplist
, &idx
);
1112 pa_memblock_unref(c
->scache
.memchunk
.memblock
);
1113 pa_memchunk_reset(&c
->scache
.memchunk
);
1115 pa_xfree(c
->scache
.name
);
1116 c
->scache
.name
= NULL
;
1118 c
->state
= ESD_NEXT_REQUEST
;
1121 connection_write(c
, &idx
, sizeof(uint32_t));
1124 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
1131 pa_assert(c
->input_memblockq
);
1133 /* pa_log("STREAMING_DATA"); */
1135 if ((l
= (size_t) pa_atomic_load(&c
->playback
.missing
)) <= 0)
1138 if (c
->playback
.current_memblock
) {
1140 space
= pa_memblock_get_length(c
->playback
.current_memblock
) - c
->playback
.memblock_index
;
1143 pa_memblock_unref(c
->playback
.current_memblock
);
1144 c
->playback
.current_memblock
= NULL
;
1148 if (!c
->playback
.current_memblock
) {
1149 pa_assert_se(c
->playback
.current_memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, (size_t) -1));
1150 c
->playback
.memblock_index
= 0;
1152 space
= pa_memblock_get_length(c
->playback
.current_memblock
);
1158 p
= pa_memblock_acquire(c
->playback
.current_memblock
);
1159 r
= pa_iochannel_read(c
->io
, (uint8_t*) p
+c
->playback
.memblock_index
, l
);
1160 pa_memblock_release(c
->playback
.current_memblock
);
1164 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1167 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1171 chunk
.memblock
= c
->playback
.current_memblock
;
1172 chunk
.index
= c
->playback
.memblock_index
;
1173 chunk
.length
= (size_t) r
;
1175 c
->playback
.memblock_index
+= (size_t) r
;
1177 pa_atomic_sub(&c
->playback
.missing
, (int) r
);
1178 pa_asyncmsgq_post(c
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(c
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, &chunk
, NULL
);
1184 static int do_write(connection
*c
) {
1185 connection_assert_ref(c
);
1187 /* pa_log("WRITE"); */
1189 if (c
->write_data_length
) {
1192 pa_assert(c
->write_data_index
< c
->write_data_length
);
1193 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) {
1195 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1198 pa_log("write(): %s", pa_cstrerror(errno
));
1202 c
->write_data_index
+= (size_t) r
;
1203 if (c
->write_data_index
>= c
->write_data_length
)
1204 c
->write_data_length
= c
->write_data_index
= 0;
1206 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->source_output
) {
1211 if (pa_memblockq_peek(c
->output_memblockq
, &chunk
) < 0)
1214 pa_assert(chunk
.memblock
);
1215 pa_assert(chunk
.length
);
1217 p
= pa_memblock_acquire(chunk
.memblock
);
1218 r
= pa_iochannel_write(c
->io
, (uint8_t*) p
+chunk
.index
, chunk
.length
);
1219 pa_memblock_release(chunk
.memblock
);
1221 pa_memblock_unref(chunk
.memblock
);
1225 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1228 pa_log("write(): %s", pa_cstrerror(errno
));
1232 pa_memblockq_drop(c
->output_memblockq
, (size_t) r
);
1238 static void do_work(connection
*c
) {
1239 connection_assert_ref(c
);
1241 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
1246 if (pa_iochannel_is_readable(c
->io
))
1250 if (c
->state
== ESD_STREAMING_DATA
&& !c
->sink_input
&& pa_iochannel_is_hungup(c
->io
))
1251 /* In case we are in capture mode we will never call read()
1252 * on the socket, hence we need to detect the hangup manually
1253 * here, instead of simply waiting for read() to return 0. */
1256 if (pa_iochannel_is_writable(c
->io
))
1257 if (do_write(c
) < 0)
1264 if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
1267 pa_iochannel_free(c
->io
);
1270 pa_asyncmsgq_post(c
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(c
->sink_input
), SINK_INPUT_MESSAGE_DISABLE_PREBUF
, NULL
, 0, NULL
, NULL
);
1272 connection_unlink(c
);
1275 static void io_callback(pa_iochannel
*io
, void *userdata
) {
1276 connection
*c
= CONNECTION(userdata
);
1278 connection_assert_ref(c
);
1284 static void defer_callback(pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
) {
1285 connection
*c
= CONNECTION(userdata
);
1287 connection_assert_ref(c
);
1293 static int connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1294 connection
*c
= CONNECTION(o
);
1295 connection_assert_ref(c
);
1301 case CONNECTION_MESSAGE_REQUEST_DATA
:
1305 case CONNECTION_MESSAGE_POST_DATA
:
1306 /* pa_log("got data %u", chunk->length); */
1307 pa_memblockq_push_align(c
->output_memblockq
, chunk
);
1311 case CONNECTION_MESSAGE_UNLINK_CONNECTION
:
1312 connection_unlink(c
);
1319 /*** sink_input callbacks ***/
1321 /* Called from thread context */
1322 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1323 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1326 pa_sink_input_assert_ref(i
);
1327 c
= CONNECTION(i
->userdata
);
1328 connection_assert_ref(c
);
1332 case SINK_INPUT_MESSAGE_POST_DATA
: {
1335 /* New data from the main loop */
1336 pa_memblockq_push_align(c
->input_memblockq
, chunk
);
1338 if (pa_memblockq_is_readable(c
->input_memblockq
) && c
->playback
.underrun
) {
1339 pa_log_debug("Requesting rewind due to end of underrun.");
1340 pa_sink_input_request_rewind(c
->sink_input
, 0, FALSE
, TRUE
, FALSE
);
1343 /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
1348 case SINK_INPUT_MESSAGE_DISABLE_PREBUF
:
1349 pa_memblockq_prebuf_disable(c
->input_memblockq
);
1352 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1353 pa_usec_t
*r
= userdata
;
1355 *r
= pa_bytes_to_usec(pa_memblockq_get_length(c
->input_memblockq
), &c
->sink_input
->sample_spec
);
1357 /* Fall through, the default handler will add in the extra
1358 * latency added by the resampler */
1362 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1366 /* Called from thread context */
1367 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
) {
1370 pa_sink_input_assert_ref(i
);
1371 c
= CONNECTION(i
->userdata
);
1372 connection_assert_ref(c
);
1375 if (pa_memblockq_peek(c
->input_memblockq
, chunk
) < 0) {
1377 c
->playback
.underrun
= TRUE
;
1379 if (c
->dead
&& pa_sink_input_safe_to_remove(i
))
1380 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_UNLINK_CONNECTION
, NULL
, 0, NULL
, NULL
);
1386 c
->playback
.underrun
= FALSE
;
1388 chunk
->length
= PA_MIN(length
, chunk
->length
);
1389 pa_memblockq_drop(c
->input_memblockq
, chunk
->length
);
1390 m
= pa_memblockq_pop_missing(c
->input_memblockq
);
1393 if (pa_atomic_add(&c
->playback
.missing
, (int) m
) <= 0)
1394 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1400 /* Called from thread context */
1401 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1404 pa_sink_input_assert_ref(i
);
1405 c
= CONNECTION(i
->userdata
);
1406 connection_assert_ref(c
);
1408 /* If we are in an underrun, then we don't rewind */
1409 if (i
->thread_info
.underrun_for
> 0)
1412 pa_memblockq_rewind(c
->input_memblockq
, nbytes
);
1415 /* Called from thread context */
1416 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1419 pa_sink_input_assert_ref(i
);
1420 c
= CONNECTION(i
->userdata
);
1421 connection_assert_ref(c
);
1423 pa_memblockq_set_maxrewind(c
->input_memblockq
, nbytes
);
1426 static void sink_input_kill_cb(pa_sink_input
*i
) {
1427 pa_sink_input_assert_ref(i
);
1429 connection_unlink(CONNECTION(i
->userdata
));
1432 /*** source_output callbacks ***/
1434 /* Called from thread context */
1435 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1438 pa_source_output_assert_ref(o
);
1439 c
= CONNECTION(o
->userdata
);
1443 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1446 static void source_output_kill_cb(pa_source_output
*o
) {
1447 pa_source_output_assert_ref(o
);
1449 connection_unlink(CONNECTION(o
->userdata
));
1452 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1455 pa_source_output_assert_ref(o
);
1456 c
= CONNECTION(o
->userdata
);
1459 return pa_bytes_to_usec(pa_memblockq_get_length(c
->output_memblockq
), &c
->source_output
->sample_spec
);
1462 /*** entry points ***/
1464 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
1465 connection
*c
= CONNECTION(userdata
);
1468 connection_assert_ref(c
);
1469 pa_assert(c
->auth_timeout_event
== e
);
1472 connection_unlink(c
);
1475 void pa_esound_protocol_connect(pa_esound_protocol
*p
, pa_iochannel
*io
, pa_esound_options
*o
) {
1478 pa_client_new_data data
;
1485 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
1486 pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
1487 pa_iochannel_free(io
);
1491 pa_client_new_data_init(&data
);
1492 data
.module
= o
->module
;
1493 data
.driver
= __FILE__
;
1494 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
1495 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "EsounD client (%s)", pname
);
1496 pa_proplist_sets(data
.proplist
, "esound-protocol.peer", pname
);
1497 client
= pa_client_new(p
->core
, &data
);
1498 pa_client_new_data_done(&data
);
1503 c
= pa_msgobject_new(connection
);
1504 c
->parent
.parent
.free
= connection_free
;
1505 c
->parent
.process_msg
= connection_process_msg
;
1508 pa_iochannel_set_callback(c
->io
, io_callback
, c
);
1511 c
->client
->kill
= client_kill_cb
;
1512 c
->client
->userdata
= c
;
1514 c
->options
= pa_esound_options_ref(o
);
1515 c
->authorized
= FALSE
;
1516 c
->swap_byte_order
= FALSE
;
1519 c
->read_data_length
= 0;
1520 c
->read_data
= pa_xmalloc(c
->read_data_alloc
= proto_map
[ESD_PROTO_CONNECT
].data_length
);
1522 c
->write_data_length
= c
->write_data_index
= c
->write_data_alloc
= 0;
1523 c
->write_data
= NULL
;
1525 c
->state
= ESD_NEEDS_REQDATA
;
1526 c
->request
= ESD_PROTO_CONNECT
;
1528 c
->sink_input
= NULL
;
1529 c
->input_memblockq
= NULL
;
1531 c
->source_output
= NULL
;
1532 c
->output_memblockq
= NULL
;
1534 c
->playback
.current_memblock
= NULL
;
1535 c
->playback
.memblock_index
= 0;
1536 c
->playback
.underrun
= TRUE
;
1537 pa_atomic_store(&c
->playback
.missing
, 0);
1539 pa_memchunk_reset(&c
->scache
.memchunk
);
1540 c
->scache
.name
= NULL
;
1542 c
->original_name
= NULL
;
1544 if (o
->auth_anonymous
) {
1545 pa_log_info("Client authenticated anonymously.");
1546 c
->authorized
= TRUE
;
1549 if (!c
->authorized
&&
1551 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
1553 pa_log_info("Client authenticated by IP ACL.");
1554 c
->authorized
= TRUE
;
1558 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
1560 c
->auth_timeout_event
= NULL
;
1562 c
->defer_event
= p
->core
->mainloop
->defer_new(p
->core
->mainloop
, defer_callback
, c
);
1563 p
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
1565 pa_idxset_put(p
->connections
, c
, &c
->index
);
1568 void pa_esound_protocol_disconnect(pa_esound_protocol
*p
, pa_module
*m
) {
1575 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
1576 if (c
->options
->module
== m
)
1577 connection_unlink(c
);
1580 static pa_esound_protocol
* esound_protocol_new(pa_core
*c
) {
1581 pa_esound_protocol
*p
;
1585 p
= pa_xnew(pa_esound_protocol
, 1);
1588 p
->connections
= pa_idxset_new(NULL
, NULL
);
1591 pa_assert_se(pa_shared_set(c
, "esound-protocol", p
) >= 0);
1596 pa_esound_protocol
* pa_esound_protocol_get(pa_core
*c
) {
1597 pa_esound_protocol
*p
;
1599 if ((p
= pa_shared_get(c
, "esound-protocol")))
1600 return pa_esound_protocol_ref(p
);
1602 return esound_protocol_new(c
);
1605 pa_esound_protocol
* pa_esound_protocol_ref(pa_esound_protocol
*p
) {
1607 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
1614 void pa_esound_protocol_unref(pa_esound_protocol
*p
) {
1617 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
1619 if (PA_REFCNT_DEC(p
) > 0)
1622 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
1623 connection_unlink(c
);
1625 pa_idxset_free(p
->connections
, NULL
, NULL
);
1627 pa_assert_se(pa_shared_remove(p
->core
, "esound-protocol") >= 0);
1632 pa_esound_options
* pa_esound_options_new(void) {
1633 pa_esound_options
*o
;
1635 o
= pa_xnew0(pa_esound_options
, 1);
1641 pa_esound_options
* pa_esound_options_ref(pa_esound_options
*o
) {
1643 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1650 void pa_esound_options_unref(pa_esound_options
*o
) {
1652 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1654 if (PA_REFCNT_DEC(o
) > 0)
1658 pa_ip_acl_free(o
->auth_ip_acl
);
1661 pa_auth_cookie_unref(o
->auth_cookie
);
1663 pa_xfree(o
->default_sink
);
1664 pa_xfree(o
->default_source
);
1669 int pa_esound_options_parse(pa_esound_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
1674 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
1677 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
1678 pa_log("auth-anonymous= expects a boolean argument.");
1682 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
1685 if (!(ipa
= pa_ip_acl_new(acl
))) {
1686 pa_log("Failed to parse IP ACL '%s'", acl
);
1691 pa_ip_acl_free(o
->auth_ip_acl
);
1693 o
->auth_ip_acl
= ipa
;
1697 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
1698 pa_log("auth-cookie-enabled= expects a boolean argument.");
1703 pa_auth_cookie_unref(o
->auth_cookie
);
1708 /* The new name for this is 'auth-cookie', for compat reasons
1709 * we check the old name too */
1710 if (!(cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
)))
1711 if (!(cn
= pa_modargs_get_value(ma
, "cookie", NULL
)))
1712 cn
= DEFAULT_COOKIE_FILE
;
1714 if (!(o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, ESD_KEY_LEN
)))
1718 o
->auth_cookie
= NULL
;
1720 pa_xfree(o
->default_sink
);
1721 o
->default_sink
= pa_xstrdup(pa_modargs_get_value(ma
, "sink", NULL
));
1723 pa_xfree(o
->default_source
);
1724 o
->default_source
= pa_xstrdup(pa_modargs_get_value(ma
, "source", NULL
));