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 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/sample.h>
34 #include <pulse/timeval.h>
35 #include <pulse/utf8.h>
36 #include <pulse/xmalloc.h>
37 #include <pulse/proplist.h>
39 #include <pulsecore/esound.h>
40 #include <pulsecore/memblock.h>
41 #include <pulsecore/client.h>
42 #include <pulsecore/sink-input.h>
43 #include <pulsecore/sink.h>
44 #include <pulsecore/source-output.h>
45 #include <pulsecore/source.h>
46 #include <pulsecore/core-scache.h>
47 #include <pulsecore/sample-util.h>
48 #include <pulsecore/authkey.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/log.h>
51 #include <pulsecore/core-util.h>
52 #include <pulsecore/core-error.h>
53 #include <pulsecore/ipacl.h>
54 #include <pulsecore/macro.h>
55 #include <pulsecore/thread-mq.h>
56 #include <pulsecore/shared.h>
58 #include "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
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_DECLARE_CLASS(connection
);
123 #define CONNECTION(o) (connection_cast(o))
124 static PA_DEFINE_CHECK_TYPE(connection
, pa_msgobject
);
126 struct pa_esound_protocol
{
130 pa_idxset
*connections
;
135 SINK_INPUT_MESSAGE_POST_DATA
= PA_SINK_INPUT_MESSAGE_MAX
, /* data from main loop to sink input */
136 SINK_INPUT_MESSAGE_DISABLE_PREBUF
140 CONNECTION_MESSAGE_REQUEST_DATA
,
141 CONNECTION_MESSAGE_POST_DATA
,
142 CONNECTION_MESSAGE_UNLINK_CONNECTION
145 typedef struct proto_handler
{
147 int (*proc
)(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
148 const char *description
;
149 } esd_proto_handler_info_t
;
151 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
);
152 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
153 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
154 static void sink_input_kill_cb(pa_sink_input
*i
);
155 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
156 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
158 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
159 static void source_output_kill_cb(pa_source_output
*o
);
161 static int esd_proto_connect(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
162 static int esd_proto_stream_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
163 static int esd_proto_stream_record(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
164 static int esd_proto_get_latency(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
165 static int esd_proto_server_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
166 static int esd_proto_all_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
167 static int esd_proto_stream_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
168 static int esd_proto_sample_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
169 static int esd_proto_sample_cache(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
170 static int esd_proto_sample_free_or_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
171 static int esd_proto_sample_get_id(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
172 static int esd_proto_standby_or_resume(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
173 static int esd_proto_standby_mode(connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
175 /* the big map of protocol handler info */
176 static struct proto_handler proto_map
[ESD_PROTO_MAX
] = {
177 { ESD_KEY_LEN
+ sizeof(int), esd_proto_connect
, "connect" },
178 { ESD_KEY_LEN
+ sizeof(int), NULL
, "lock" },
179 { ESD_KEY_LEN
+ sizeof(int), NULL
, "unlock" },
181 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_play
, "stream play" },
182 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream rec" },
183 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream mon" },
185 { ESD_NAME_MAX
+ 3 * sizeof(int), esd_proto_sample_cache
, "sample cache" }, /* 6 */
186 { sizeof(int), esd_proto_sample_free_or_play
, "sample free" },
187 { sizeof(int), esd_proto_sample_free_or_play
, "sample play" }, /* 8 */
188 { sizeof(int), NULL
, "sample loop" },
189 { sizeof(int), NULL
, "sample stop" },
190 { (size_t) -1, NULL
, "TODO: sample kill" },
192 { ESD_KEY_LEN
+ sizeof(int), esd_proto_standby_or_resume
, "standby" },
193 { ESD_KEY_LEN
+ sizeof(int), esd_proto_standby_or_resume
, "resume" }, /* 13 */
195 { ESD_NAME_MAX
, esd_proto_sample_get_id
, "sample getid" }, /* 14 */
196 { ESD_NAME_MAX
+ 2 * sizeof(int), NULL
, "stream filter" },
198 { sizeof(int), esd_proto_server_info
, "server info" },
199 { sizeof(int), esd_proto_all_info
, "all info" },
200 { (size_t) -1, NULL
, "TODO: subscribe" },
201 { (size_t) -1, NULL
, "TODO: unsubscribe" },
203 { 3 * sizeof(int), esd_proto_stream_pan
, "stream pan"},
204 { 3 * sizeof(int), esd_proto_sample_pan
, "sample pan" },
206 { sizeof(int), esd_proto_standby_mode
, "standby mode" },
207 { 0, esd_proto_get_latency
, "get latency" }
210 static void connection_unlink(connection
*c
) {
217 pa_esound_options_unref(c
->options
);
222 pa_sink_input_unlink(c
->sink_input
);
223 pa_sink_input_unref(c
->sink_input
);
224 c
->sink_input
= NULL
;
227 if (c
->source_output
) {
228 pa_source_output_unlink(c
->source_output
);
229 pa_source_output_unref(c
->source_output
);
230 c
->source_output
= NULL
;
234 pa_client_free(c
->client
);
238 if (c
->state
== ESD_STREAMING_DATA
)
239 c
->protocol
->n_player
--;
242 pa_iochannel_free(c
->io
);
246 if (c
->defer_event
) {
247 c
->protocol
->core
->mainloop
->defer_free(c
->defer_event
);
248 c
->defer_event
= NULL
;
251 if (c
->auth_timeout_event
) {
252 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
253 c
->auth_timeout_event
= NULL
;
256 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
261 static void connection_free(pa_object
*obj
) {
262 connection
*c
= CONNECTION(obj
);
265 if (c
->input_memblockq
)
266 pa_memblockq_free(c
->input_memblockq
);
267 if (c
->output_memblockq
)
268 pa_memblockq_free(c
->output_memblockq
);
270 if (c
->playback
.current_memblock
)
271 pa_memblock_unref(c
->playback
.current_memblock
);
273 pa_xfree(c
->read_data
);
274 pa_xfree(c
->write_data
);
276 if (c
->scache
.memchunk
.memblock
)
277 pa_memblock_unref(c
->scache
.memchunk
.memblock
);
278 pa_xfree(c
->scache
.name
);
280 pa_xfree(c
->original_name
);
284 static void connection_write_prepare(connection
*c
, size_t length
) {
288 t
= c
->write_data_length
+length
;
290 if (c
->write_data_alloc
< t
)
291 c
->write_data
= pa_xrealloc(c
->write_data
, c
->write_data_alloc
= t
);
293 pa_assert(c
->write_data
);
296 static void connection_write(connection
*c
, const void *data
, size_t length
) {
300 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
302 connection_write_prepare(c
, length
);
304 pa_assert(c
->write_data
);
306 i
= c
->write_data_length
;
307 c
->write_data_length
+= length
;
309 memcpy((uint8_t*) c
->write_data
+ i
, data
, length
);
312 static void format_esd2native(int format
, pa_bool_t swap_bytes
, pa_sample_spec
*ss
) {
315 ss
->channels
= (uint8_t) (((format
& ESD_MASK_CHAN
) == ESD_STEREO
) ? 2 : 1);
316 if ((format
& ESD_MASK_BITS
) == ESD_BITS16
)
317 ss
->format
= swap_bytes
? PA_SAMPLE_S16RE
: PA_SAMPLE_S16NE
;
319 ss
->format
= PA_SAMPLE_U8
;
322 static int format_native2esd(pa_sample_spec
*ss
) {
325 format
= (ss
->format
== PA_SAMPLE_U8
) ? ESD_BITS8
: ESD_BITS16
;
326 format
|= (ss
->channels
>= 2) ? ESD_STEREO
: ESD_MONO
;
331 #define CHECK_VALIDITY(expression, ...) do { \
332 if (!(expression)) { \
333 pa_log_warn(__FILE__ ": " __VA_ARGS__); \
338 /*** esound commands ***/
340 static int esd_proto_connect(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
344 connection_assert_ref(c
);
346 pa_assert(length
== (ESD_KEY_LEN
+ sizeof(uint32_t)));
348 if (!c
->authorized
&& c
->options
->auth_cookie
) {
351 if ((key
= pa_auth_cookie_read(c
->options
->auth_cookie
, ESD_KEY_LEN
)))
352 if (memcmp(data
, key
, ESD_KEY_LEN
) == 0)
353 c
->authorized
= TRUE
;
356 if (!c
->authorized
) {
357 pa_log("Kicked client with invalid authorization key.");
361 if (c
->auth_timeout_event
) {
362 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
363 c
->auth_timeout_event
= NULL
;
366 data
= (const char*)data
+ ESD_KEY_LEN
;
368 memcpy(&ekey
, data
, sizeof(uint32_t));
369 if (ekey
== ESD_ENDIAN_KEY
)
370 c
->swap_byte_order
= FALSE
;
371 else if (ekey
== ESD_SWAP_ENDIAN_KEY
)
372 c
->swap_byte_order
= TRUE
;
374 pa_log_warn("Client sent invalid endian key");
378 pa_proplist_sets(c
->client
->proplist
, "esound.byte_order", c
->swap_byte_order
? "reverse" : "native");
381 connection_write(c
, &ok
, sizeof(int));
385 static int esd_proto_stream_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
386 char name
[ESD_NAME_MAX
], *utf8_name
;
387 int32_t format
, rate
;
390 pa_sink
*sink
= NULL
;
391 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_sample_spec(&sdata
, &ss
);
432 pa_sink_input_new(&c
->sink_input
, c
->protocol
->core
, &sdata
, 0);
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 c
->input_memblockq
= pa_memblockq_new(
444 l
/PLAYBACK_BUFFER_FRAGMENTS
,
447 pa_iochannel_socket_set_rcvbuf(c
->io
, l
);
449 c
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
450 c
->sink_input
->pop
= sink_input_pop_cb
;
451 c
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
452 c
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
453 c
->sink_input
->kill
= sink_input_kill_cb
;
454 c
->sink_input
->userdata
= c
;
456 pa_sink_input_set_requested_latency(c
->sink_input
, DEFAULT_SINK_LATENCY
);
458 c
->state
= ESD_STREAMING_DATA
;
460 c
->protocol
->n_player
++;
462 pa_atomic_store(&c
->playback
.missing
, (int) pa_memblockq_missing(c
->input_memblockq
));
464 pa_sink_input_put(c
->sink_input
);
469 static int esd_proto_stream_record(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
470 char name
[ESD_NAME_MAX
], *utf8_name
;
471 int32_t format
, rate
;
472 pa_source
*source
= NULL
;
475 pa_source_output_new_data sdata
;
477 connection_assert_ref(c
);
479 pa_assert(length
== (sizeof(int32_t)*2+ESD_NAME_MAX
));
481 memcpy(&format
, data
, sizeof(int32_t));
482 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
483 data
= (const char*) data
+ sizeof(int32_t);
485 memcpy(&rate
, data
, sizeof(int32_t));
486 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
487 data
= (const char*) data
+ sizeof(int32_t);
489 ss
.rate
= (uint32_t) rate
;
490 format_esd2native(format
, c
->swap_byte_order
, &ss
);
492 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification.");
494 if (request
== ESD_PROTO_STREAM_MON
) {
497 sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
);
498 CHECK_VALIDITY(sink
, "No such sink: %s", pa_strnull(c
->options
->default_sink
));
500 source
= sink
->monitor_source
;
501 CHECK_VALIDITY(source
, "No such source.");
503 pa_assert(request
== ESD_PROTO_STREAM_REC
);
505 if (c
->options
->default_source
) {
506 source
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_source
, PA_NAMEREG_SOURCE
);
507 CHECK_VALIDITY(source
, "No such source: %s", pa_strnull(c
->options
->default_source
));
511 pa_strlcpy(name
, data
, sizeof(name
));
513 utf8_name
= pa_utf8_filter(name
);
514 pa_client_set_name(c
->client
, utf8_name
);
517 c
->original_name
= pa_xstrdup(name
);
519 pa_assert(!c
->output_memblockq
&& !c
->source_output
);
521 pa_source_output_new_data_init(&sdata
);
522 sdata
.driver
= __FILE__
;
523 sdata
.module
= c
->options
->module
;
524 sdata
.client
= c
->client
;
525 sdata
.source
= source
;
526 pa_source_output_new_data_set_sample_spec(&sdata
, &ss
);
528 pa_source_output_new(&c
->source_output
, c
->protocol
->core
, &sdata
, 0);
529 pa_source_output_new_data_done(&sdata
);
531 CHECK_VALIDITY(c
->source_output
, "Failed to create source output.");
533 l
= (size_t) (pa_bytes_per_second(&ss
)*RECORD_BUFFER_SECONDS
);
534 c
->output_memblockq
= pa_memblockq_new(
543 pa_iochannel_socket_set_sndbuf(c
->io
, l
);
545 c
->source_output
->push
= source_output_push_cb
;
546 c
->source_output
->kill
= source_output_kill_cb
;
547 c
->source_output
->get_latency
= source_output_get_latency_cb
;
548 c
->source_output
->userdata
= c
;
550 pa_source_output_set_requested_latency(c
->source_output
, DEFAULT_SOURCE_LATENCY
);
552 c
->state
= ESD_STREAMING_DATA
;
554 c
->protocol
->n_player
++;
556 pa_source_output_put(c
->source_output
);
561 static int esd_proto_get_latency(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
567 pa_assert(length
== 0);
569 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
572 double usec
= (double) pa_sink_get_requested_latency(sink
);
573 latency
= (int) ((usec
*44100)/1000000);
576 latency
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, latency
);
577 connection_write(c
, &latency
, sizeof(int32_t));
581 static int esd_proto_server_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
582 int32_t rate
= 44100, format
= ESD_STEREO
|ESD_BITS16
;
588 pa_assert(length
== sizeof(int32_t));
590 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
))) {
591 rate
= (int32_t) sink
->sample_spec
.rate
;
592 format
= format_native2esd(&sink
->sample_spec
);
595 connection_write_prepare(c
, sizeof(int32_t) * 3);
598 connection_write(c
, &response
, sizeof(int32_t));
599 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
600 connection_write(c
, &rate
, sizeof(int32_t));
601 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
602 connection_write(c
, &format
, sizeof(int32_t));
607 static int esd_proto_all_info(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
610 uint32_t idx
= PA_IDXSET_INVALID
;
612 char terminator
[sizeof(int32_t)*6+ESD_NAME_MAX
];
616 pa_assert(length
== sizeof(int32_t));
618 if (esd_proto_server_info(c
, request
, data
, length
) < 0)
621 k
= sizeof(int32_t)*5+ESD_NAME_MAX
;
622 s
= sizeof(int32_t)*6+ESD_NAME_MAX
;
623 nsamples
= pa_idxset_size(c
->protocol
->core
->scache
);
624 t
= s
*(nsamples
+1) + k
*(c
->protocol
->n_player
+1);
626 connection_write_prepare(c
, t
);
628 memset(terminator
, 0, sizeof(terminator
));
630 for (conn
= pa_idxset_first(c
->protocol
->connections
, &idx
); conn
; conn
= pa_idxset_next(c
->protocol
->connections
, &idx
)) {
631 int32_t id
, format
= ESD_BITS16
| ESD_STEREO
, rate
= 44100, lvolume
= ESD_VOLUME_BASE
, rvolume
= ESD_VOLUME_BASE
;
632 char name
[ESD_NAME_MAX
];
634 if (conn
->state
!= ESD_STREAMING_DATA
)
637 pa_assert(t
>= k
*2+s
);
639 if (conn
->sink_input
) {
640 pa_cvolume volume
= *pa_sink_input_get_volume(conn
->sink_input
);
641 rate
= (int32_t) conn
->sink_input
->sample_spec
.rate
;
642 lvolume
= (int32_t) ((volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
643 rvolume
= (int32_t) ((volume
.values
[volume
.channels
== 2 ? 1 : 0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
644 format
= format_native2esd(&conn
->sink_input
->sample_spec
);
648 id
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) (conn
->index
+1));
649 connection_write(c
, &id
, sizeof(int32_t));
652 memset(name
, 0, ESD_NAME_MAX
); /* don't leak old data */
653 if (conn
->original_name
)
654 strncpy(name
, conn
->original_name
, ESD_NAME_MAX
);
655 else if (conn
->client
&& pa_proplist_gets(conn
->client
->proplist
, PA_PROP_APPLICATION_NAME
))
656 strncpy(name
, pa_proplist_gets(conn
->client
->proplist
, PA_PROP_APPLICATION_NAME
), ESD_NAME_MAX
);
657 connection_write(c
, name
, ESD_NAME_MAX
);
660 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
661 connection_write(c
, &rate
, sizeof(int32_t));
664 lvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, lvolume
);
665 connection_write(c
, &lvolume
, sizeof(int32_t));
668 rvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rvolume
);
669 connection_write(c
, &rvolume
, sizeof(int32_t));
672 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
673 connection_write(c
, &format
, sizeof(int32_t));
678 pa_assert(t
== s
*(nsamples
+1)+k
);
681 connection_write(c
, terminator
, k
);
686 idx
= PA_IDXSET_INVALID
;
687 for (ce
= pa_idxset_first(c
->protocol
->core
->scache
, &idx
); ce
; ce
= pa_idxset_next(c
->protocol
->core
->scache
, &idx
)) {
688 int32_t id
, rate
, lvolume
, rvolume
, format
, len
;
689 char name
[ESD_NAME_MAX
];
690 pa_channel_map stereo
= { .channels
= 2, .map
= { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
} };
696 if (ce
->volume_is_set
) {
698 pa_cvolume_remap(&volume
, &ce
->channel_map
, &stereo
);
700 pa_cvolume_reset(&volume
, 2);
702 if (ce
->memchunk
.memblock
)
703 ss
= ce
->sample_spec
;
705 ss
.format
= PA_SAMPLE_S16NE
;
711 id
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) (ce
->index
+1));
712 connection_write(c
, &id
, sizeof(int32_t));
715 memset(name
, 0, ESD_NAME_MAX
); /* don't leak old data */
716 if (strncmp(ce
->name
, SCACHE_PREFIX
, sizeof(SCACHE_PREFIX
)-1) == 0)
717 strncpy(name
, ce
->name
+sizeof(SCACHE_PREFIX
)-1, ESD_NAME_MAX
);
719 pa_snprintf(name
, ESD_NAME_MAX
, "native.%s", ce
->name
);
720 connection_write(c
, name
, ESD_NAME_MAX
);
723 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ss
.rate
);
724 connection_write(c
, &rate
, sizeof(int32_t));
727 lvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ((volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
));
728 connection_write(c
, &lvolume
, sizeof(int32_t));
731 rvolume
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) ((volume
.values
[1]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
));
732 connection_write(c
, &rvolume
, sizeof(int32_t));
735 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format_native2esd(&ss
));
736 connection_write(c
, &format
, sizeof(int32_t));
739 len
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) ce
->memchunk
.length
);
740 connection_write(c
, &len
, sizeof(int32_t));
748 connection_write(c
, terminator
, s
);
753 static int esd_proto_stream_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
755 uint32_t idx
, lvolume
, rvolume
;
758 connection_assert_ref(c
);
760 pa_assert(length
== sizeof(int32_t)*3);
762 memcpy(&idx
, data
, sizeof(uint32_t));
763 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
764 data
= (const char*)data
+ sizeof(uint32_t);
766 memcpy(&lvolume
, data
, sizeof(uint32_t));
767 lvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
768 data
= (const char*)data
+ sizeof(uint32_t);
770 memcpy(&rvolume
, data
, sizeof(uint32_t));
771 rvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
772 data
= (const char*)data
+ sizeof(uint32_t);
774 if ((conn
= pa_idxset_get_by_index(c
->protocol
->connections
, idx
)) && conn
->sink_input
) {
776 volume
.values
[0] = (lvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
777 volume
.values
[1] = (rvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
778 volume
.channels
= conn
->sink_input
->sample_spec
.channels
;
780 pa_sink_input_set_volume(conn
->sink_input
, &volume
, TRUE
);
785 connection_write(c
, &ok
, sizeof(int32_t));
790 static int esd_proto_sample_pan(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
792 uint32_t idx
, lvolume
, rvolume
;
796 connection_assert_ref(c
);
798 pa_assert(length
== sizeof(int32_t)*3);
800 memcpy(&idx
, data
, sizeof(uint32_t));
801 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
802 data
= (const char*)data
+ sizeof(uint32_t);
804 memcpy(&lvolume
, data
, sizeof(uint32_t));
805 lvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
806 data
= (const char*)data
+ sizeof(uint32_t);
808 memcpy(&rvolume
, data
, sizeof(uint32_t));
809 rvolume
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
810 data
= (const char*)data
+ sizeof(uint32_t);
812 volume
.values
[0] = (lvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
813 volume
.values
[1] = (rvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
816 if ((ce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
))) {
817 pa_channel_map stereo
= { .channels
= 2, .map
= { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
} };
819 pa_cvolume_remap(&volume
, &stereo
, &ce
->channel_map
);
821 ce
->volume_is_set
= TRUE
;
825 connection_write(c
, &ok
, sizeof(int32_t));
830 static int esd_proto_sample_cache(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
832 int32_t format
, rate
, sc_length
;
834 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
836 connection_assert_ref(c
);
838 pa_assert(length
== (ESD_NAME_MAX
+3*sizeof(int32_t)));
840 memcpy(&format
, data
, sizeof(int32_t));
841 format
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
842 data
= (const char*)data
+ sizeof(int32_t);
844 memcpy(&rate
, data
, sizeof(int32_t));
845 rate
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
846 data
= (const char*)data
+ sizeof(int32_t);
848 ss
.rate
= (uint32_t) rate
;
849 format_esd2native(format
, c
->swap_byte_order
, &ss
);
851 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification.");
853 memcpy(&sc_length
, data
, sizeof(int32_t));
854 sc_length
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, sc_length
);
855 data
= (const char*)data
+ sizeof(int32_t);
857 CHECK_VALIDITY(sc_length
<= MAX_CACHE_SAMPLE_SIZE
, "Sample too large (%d bytes).", (int)sc_length
);
859 strcpy(name
, SCACHE_PREFIX
);
860 pa_strlcpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
862 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in sample name.");
864 pa_assert(!c
->scache
.memchunk
.memblock
);
865 c
->scache
.memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, (size_t) sc_length
);
866 c
->scache
.memchunk
.index
= 0;
867 c
->scache
.memchunk
.length
= (size_t) sc_length
;
868 c
->scache
.sample_spec
= ss
;
869 pa_assert(!c
->scache
.name
);
870 c
->scache
.name
= pa_xstrdup(name
);
872 c
->state
= ESD_CACHING_SAMPLE
;
874 pa_scache_add_item(c
->protocol
->core
, c
->scache
.name
, NULL
, NULL
, NULL
, c
->client
->proplist
, &idx
);
877 connection_write(c
, &idx
, sizeof(uint32_t));
882 static int esd_proto_sample_get_id(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
885 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
887 connection_assert_ref(c
);
889 pa_assert(length
== ESD_NAME_MAX
);
891 strcpy(name
, SCACHE_PREFIX
);
892 pa_strlcpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
894 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in sample name.");
897 if ((idx
= pa_scache_get_id_by_name(c
->protocol
->core
, name
)) != PA_IDXSET_INVALID
)
898 ok
= (int32_t) idx
+ 1;
900 connection_write(c
, &ok
, sizeof(int32_t));
905 static int esd_proto_sample_free_or_play(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
910 connection_assert_ref(c
);
912 pa_assert(length
== sizeof(int32_t));
914 memcpy(&idx
, data
, sizeof(uint32_t));
915 idx
= PA_MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
919 if ((name
= pa_scache_get_name_by_id(c
->protocol
->core
, idx
))) {
920 if (request
== ESD_PROTO_SAMPLE_PLAY
) {
923 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
924 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, PA_VOLUME_NORM
, c
->client
->proplist
, NULL
) >= 0)
925 ok
= (int32_t) idx
+ 1;
927 pa_assert(request
== ESD_PROTO_SAMPLE_FREE
);
929 if (pa_scache_remove_item(c
->protocol
->core
, name
) >= 0)
930 ok
= (int32_t) idx
+ 1;
934 connection_write(c
, &ok
, sizeof(int32_t));
939 static int esd_proto_standby_or_resume(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
942 connection_assert_ref(c
);
944 connection_write_prepare(c
, sizeof(int32_t) * 2);
945 connection_write(c
, &ok
, sizeof(int32_t));
947 if (request
== ESD_PROTO_STANDBY
)
948 ok
= pa_sink_suspend_all(c
->protocol
->core
, TRUE
) >= 0;
950 pa_assert(request
== ESD_PROTO_RESUME
);
951 ok
= pa_sink_suspend_all(c
->protocol
->core
, FALSE
) >= 0;
954 connection_write(c
, &ok
, sizeof(int32_t));
959 static int esd_proto_standby_mode(connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
961 pa_sink
*sink
, *source
;
963 connection_assert_ref(c
);
967 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_sink
, PA_NAMEREG_SINK
)))
968 if (pa_sink_get_state(sink
) == PA_SINK_SUSPENDED
)
969 mode
= ESM_ON_STANDBY
;
971 if ((source
= pa_namereg_get(c
->protocol
->core
, c
->options
->default_source
, PA_NAMEREG_SOURCE
)))
972 if (pa_source_get_state(source
) == PA_SOURCE_SUSPENDED
)
973 mode
= ESM_ON_STANDBY
;
975 mode
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, mode
);
977 connection_write(c
, &mode
, sizeof(mode
));
981 /*** client callbacks ***/
983 static void client_kill_cb(pa_client
*c
) {
986 connection_unlink(CONNECTION(c
->userdata
));
989 /*** pa_iochannel callbacks ***/
991 static int do_read(connection
*c
) {
992 connection_assert_ref(c
);
994 /* pa_log("READ"); */
996 if (c
->state
== ESD_NEXT_REQUEST
) {
998 pa_assert(c
->read_data_length
< sizeof(c
->request
));
1000 if ((r
= pa_iochannel_read(c
->io
,
1001 ((uint8_t*) &c
->request
) + c
->read_data_length
,
1002 sizeof(c
->request
) - c
->read_data_length
)) <= 0) {
1004 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1007 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1011 c
->read_data_length
+= (size_t) r
;
1013 if (c
->read_data_length
>= sizeof(c
->request
)) {
1014 struct proto_handler
*handler
;
1016 c
->request
= PA_MAYBE_INT32_SWAP(c
->swap_byte_order
, c
->request
);
1018 if (c
->request
< ESD_PROTO_CONNECT
|| c
->request
>= ESD_PROTO_MAX
) {
1019 pa_log("recieved invalid request.");
1023 handler
= proto_map
+c
->request
;
1025 /* pa_log("executing request #%u", c->request); */
1027 if (!handler
->proc
) {
1028 pa_log("recieved unimplemented request #%u.", c
->request
);
1032 if (handler
->data_length
== 0) {
1033 c
->read_data_length
= 0;
1035 if (handler
->proc(c
, c
->request
, NULL
, 0) < 0)
1039 if (c
->read_data_alloc
< handler
->data_length
)
1040 c
->read_data
= pa_xrealloc(c
->read_data
, c
->read_data_alloc
= handler
->data_length
);
1041 pa_assert(c
->read_data
);
1043 c
->state
= ESD_NEEDS_REQDATA
;
1044 c
->read_data_length
= 0;
1048 } else if (c
->state
== ESD_NEEDS_REQDATA
) {
1050 struct proto_handler
*handler
= proto_map
+c
->request
;
1052 pa_assert(handler
->proc
);
1054 pa_assert(c
->read_data
&& c
->read_data_length
< handler
->data_length
);
1056 if ((r
= pa_iochannel_read(c
->io
,
1057 (uint8_t*) c
->read_data
+ c
->read_data_length
,
1058 handler
->data_length
- c
->read_data_length
)) <= 0) {
1060 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1063 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1067 c
->read_data_length
+= (size_t) r
;
1068 if (c
->read_data_length
>= handler
->data_length
) {
1069 size_t l
= c
->read_data_length
;
1070 pa_assert(handler
->proc
);
1072 c
->state
= ESD_NEXT_REQUEST
;
1073 c
->read_data_length
= 0;
1075 if (handler
->proc(c
, c
->request
, c
->read_data
, l
) < 0)
1078 } else if (c
->state
== ESD_CACHING_SAMPLE
) {
1082 pa_assert(c
->scache
.memchunk
.memblock
);
1083 pa_assert(c
->scache
.name
);
1084 pa_assert(c
->scache
.memchunk
.index
< c
->scache
.memchunk
.length
);
1086 p
= pa_memblock_acquire(c
->scache
.memchunk
.memblock
);
1087 r
= pa_iochannel_read(c
->io
, (uint8_t*) p
+c
->scache
.memchunk
.index
, c
->scache
.memchunk
.length
-c
->scache
.memchunk
.index
);
1088 pa_memblock_release(c
->scache
.memchunk
.memblock
);
1091 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1094 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1098 c
->scache
.memchunk
.index
+= (size_t) r
;
1099 pa_assert(c
->scache
.memchunk
.index
<= c
->scache
.memchunk
.length
);
1101 if (c
->scache
.memchunk
.index
== c
->scache
.memchunk
.length
) {
1104 c
->scache
.memchunk
.index
= 0;
1105 pa_scache_add_item(c
->protocol
->core
, c
->scache
.name
, &c
->scache
.sample_spec
, NULL
, &c
->scache
.memchunk
, c
->client
->proplist
, &idx
);
1107 pa_memblock_unref(c
->scache
.memchunk
.memblock
);
1108 c
->scache
.memchunk
.memblock
= NULL
;
1109 c
->scache
.memchunk
.index
= c
->scache
.memchunk
.length
= 0;
1111 pa_xfree(c
->scache
.name
);
1112 c
->scache
.name
= NULL
;
1114 c
->state
= ESD_NEXT_REQUEST
;
1117 connection_write(c
, &idx
, sizeof(uint32_t));
1120 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
1127 pa_assert(c
->input_memblockq
);
1129 /* pa_log("STREAMING_DATA"); */
1131 if (!(l
= (size_t) pa_atomic_load(&c
->playback
.missing
)))
1134 if (c
->playback
.current_memblock
) {
1136 space
= pa_memblock_get_length(c
->playback
.current_memblock
) - c
->playback
.memblock_index
;
1139 pa_memblock_unref(c
->playback
.current_memblock
);
1140 c
->playback
.current_memblock
= NULL
;
1144 if (!c
->playback
.current_memblock
) {
1145 pa_assert_se(c
->playback
.current_memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, (size_t) -1));
1146 c
->playback
.memblock_index
= 0;
1148 space
= pa_memblock_get_length(c
->playback
.current_memblock
);
1154 p
= pa_memblock_acquire(c
->playback
.current_memblock
);
1155 r
= pa_iochannel_read(c
->io
, (uint8_t*) p
+c
->playback
.memblock_index
, l
);
1156 pa_memblock_release(c
->playback
.current_memblock
);
1160 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1163 pa_log_debug("read(): %s", r
< 0 ? pa_cstrerror(errno
) : "EOF");
1167 chunk
.memblock
= c
->playback
.current_memblock
;
1168 chunk
.index
= c
->playback
.memblock_index
;
1169 chunk
.length
= (size_t) r
;
1171 c
->playback
.memblock_index
+= (size_t) r
;
1173 pa_asyncmsgq_post(c
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(c
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, &chunk
, NULL
);
1174 pa_atomic_sub(&c
->playback
.missing
, (int) r
);
1180 static int do_write(connection
*c
) {
1181 connection_assert_ref(c
);
1183 /* pa_log("WRITE"); */
1185 if (c
->write_data_length
) {
1188 pa_assert(c
->write_data_index
< c
->write_data_length
);
1189 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) {
1191 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1194 pa_log("write(): %s", pa_cstrerror(errno
));
1198 c
->write_data_index
+= (size_t) r
;
1199 if (c
->write_data_index
>= c
->write_data_length
)
1200 c
->write_data_length
= c
->write_data_index
= 0;
1202 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->source_output
) {
1207 if (pa_memblockq_peek(c
->output_memblockq
, &chunk
) < 0)
1210 pa_assert(chunk
.memblock
);
1211 pa_assert(chunk
.length
);
1213 p
= pa_memblock_acquire(chunk
.memblock
);
1214 r
= pa_iochannel_write(c
->io
, (uint8_t*) p
+chunk
.index
, chunk
.length
);
1215 pa_memblock_release(chunk
.memblock
);
1217 pa_memblock_unref(chunk
.memblock
);
1221 if (r
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
1224 pa_log("write(): %s", pa_cstrerror(errno
));
1228 pa_memblockq_drop(c
->output_memblockq
, (size_t) r
);
1234 static void do_work(connection
*c
) {
1235 connection_assert_ref(c
);
1237 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
1242 if (pa_iochannel_is_readable(c
->io
))
1246 if (c
->state
== ESD_STREAMING_DATA
&& !c
->sink_input
&& pa_iochannel_is_hungup(c
->io
))
1247 /* In case we are in capture mode we will never call read()
1248 * on the socket, hence we need to detect the hangup manually
1249 * here, instead of simply waiting for read() to return 0. */
1252 if (pa_iochannel_is_writable(c
->io
))
1253 if (do_write(c
) < 0)
1260 if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
1263 pa_iochannel_free(c
->io
);
1266 pa_asyncmsgq_post(c
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(c
->sink_input
), SINK_INPUT_MESSAGE_DISABLE_PREBUF
, NULL
, 0, NULL
, NULL
);
1268 connection_unlink(c
);
1271 static void io_callback(pa_iochannel
*io
, void *userdata
) {
1272 connection
*c
= CONNECTION(userdata
);
1274 connection_assert_ref(c
);
1280 static void defer_callback(pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
) {
1281 connection
*c
= CONNECTION(userdata
);
1283 connection_assert_ref(c
);
1289 static int connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1290 connection
*c
= CONNECTION(o
);
1291 connection_assert_ref(c
);
1294 case CONNECTION_MESSAGE_REQUEST_DATA
:
1298 case CONNECTION_MESSAGE_POST_DATA
:
1299 /* pa_log("got data %u", chunk->length); */
1300 pa_memblockq_push_align(c
->output_memblockq
, chunk
);
1304 case CONNECTION_MESSAGE_UNLINK_CONNECTION
:
1305 connection_unlink(c
);
1312 /*** sink_input callbacks ***/
1314 /* Called from thread context */
1315 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1316 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1319 pa_sink_input_assert_ref(i
);
1320 c
= CONNECTION(i
->userdata
);
1321 connection_assert_ref(c
);
1325 case SINK_INPUT_MESSAGE_POST_DATA
: {
1328 /* New data from the main loop */
1329 pa_memblockq_push_align(c
->input_memblockq
, chunk
);
1331 if (pa_memblockq_is_readable(c
->input_memblockq
) && c
->playback
.underrun
) {
1332 pa_log_debug("Requesting rewind due to end of underrun.");
1333 pa_sink_input_request_rewind(c
->sink_input
, 0, FALSE
, TRUE
, FALSE
);
1336 /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
1341 case SINK_INPUT_MESSAGE_DISABLE_PREBUF
:
1342 pa_memblockq_prebuf_disable(c
->input_memblockq
);
1345 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1346 pa_usec_t
*r
= userdata
;
1348 *r
= pa_bytes_to_usec(pa_memblockq_get_length(c
->input_memblockq
), &c
->sink_input
->sample_spec
);
1350 /* Fall through, the default handler will add in the extra
1351 * latency added by the resampler */
1355 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1359 /* Called from thread context */
1360 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
) {
1363 pa_sink_input_assert_ref(i
);
1364 c
= CONNECTION(i
->userdata
);
1365 connection_assert_ref(c
);
1368 if (pa_memblockq_peek(c
->input_memblockq
, chunk
) < 0) {
1370 c
->playback
.underrun
= TRUE
;
1372 if (c
->dead
&& pa_sink_input_safe_to_remove(i
))
1373 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_UNLINK_CONNECTION
, NULL
, 0, NULL
, NULL
);
1379 chunk
->length
= PA_MIN(length
, chunk
->length
);
1381 c
->playback
.underrun
= FALSE
;
1383 pa_memblockq_drop(c
->input_memblockq
, chunk
->length
);
1384 m
= pa_memblockq_pop_missing(c
->input_memblockq
);
1387 if (pa_atomic_add(&c
->playback
.missing
, (int) m
) <= 0)
1388 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1394 /* Called from thread context */
1395 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1398 pa_sink_input_assert_ref(i
);
1399 c
= CONNECTION(i
->userdata
);
1400 connection_assert_ref(c
);
1402 /* If we are in an underrun, then we don't rewind */
1403 if (i
->thread_info
.underrun_for
> 0)
1406 pa_memblockq_rewind(c
->input_memblockq
, nbytes
);
1409 /* Called from thread context */
1410 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1413 pa_sink_input_assert_ref(i
);
1414 c
= CONNECTION(i
->userdata
);
1415 connection_assert_ref(c
);
1417 pa_memblockq_set_maxrewind(c
->input_memblockq
, nbytes
);
1420 static void sink_input_kill_cb(pa_sink_input
*i
) {
1421 pa_sink_input_assert_ref(i
);
1423 connection_unlink(CONNECTION(i
->userdata
));
1426 /*** source_output callbacks ***/
1428 /* Called from thread context */
1429 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1432 pa_source_output_assert_ref(o
);
1433 c
= CONNECTION(o
->userdata
);
1437 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(c
), CONNECTION_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1440 static void source_output_kill_cb(pa_source_output
*o
) {
1441 pa_source_output_assert_ref(o
);
1443 connection_unlink(CONNECTION(o
->userdata
));
1446 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1449 pa_source_output_assert_ref(o
);
1450 c
= CONNECTION(o
->userdata
);
1453 return pa_bytes_to_usec(pa_memblockq_get_length(c
->output_memblockq
), &c
->source_output
->sample_spec
);
1456 /*** entry points ***/
1458 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*tv
, void *userdata
) {
1459 connection
*c
= CONNECTION(userdata
);
1463 connection_assert_ref(c
);
1464 pa_assert(c
->auth_timeout_event
== e
);
1467 connection_unlink(c
);
1470 void pa_esound_protocol_connect(pa_esound_protocol
*p
, pa_iochannel
*io
, pa_esound_options
*o
) {
1473 pa_client_new_data data
;
1480 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
1481 pa_log("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
1482 pa_iochannel_free(io
);
1486 pa_client_new_data_init(&data
);
1487 data
.module
= o
->module
;
1488 data
.driver
= __FILE__
;
1489 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
1490 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "EsounD client (%s)", pname
);
1491 pa_proplist_sets(data
.proplist
, "esound-protocol.peer", pname
);
1492 client
= pa_client_new(p
->core
, &data
);
1493 pa_client_new_data_done(&data
);
1498 c
= pa_msgobject_new(connection
);
1499 c
->parent
.parent
.free
= connection_free
;
1500 c
->parent
.process_msg
= connection_process_msg
;
1503 pa_iochannel_set_callback(c
->io
, io_callback
, c
);
1506 c
->client
->kill
= client_kill_cb
;
1507 c
->client
->userdata
= c
;
1509 c
->options
= pa_esound_options_ref(o
);
1510 c
->authorized
= FALSE
;
1511 c
->swap_byte_order
= FALSE
;
1514 c
->read_data_length
= 0;
1515 c
->read_data
= pa_xmalloc(c
->read_data_alloc
= proto_map
[ESD_PROTO_CONNECT
].data_length
);
1517 c
->write_data_length
= c
->write_data_index
= c
->write_data_alloc
= 0;
1518 c
->write_data
= NULL
;
1520 c
->state
= ESD_NEEDS_REQDATA
;
1521 c
->request
= ESD_PROTO_CONNECT
;
1523 c
->sink_input
= NULL
;
1524 c
->input_memblockq
= NULL
;
1526 c
->source_output
= NULL
;
1527 c
->output_memblockq
= NULL
;
1529 c
->playback
.current_memblock
= NULL
;
1530 c
->playback
.memblock_index
= 0;
1531 c
->playback
.underrun
= TRUE
;
1532 pa_atomic_store(&c
->playback
.missing
, 0);
1534 pa_memchunk_reset(&c
->scache
.memchunk
);
1535 c
->scache
.name
= NULL
;
1537 c
->original_name
= NULL
;
1539 if (o
->auth_anonymous
) {
1540 pa_log_info("Client authenticated anonymously.");
1541 c
->authorized
= TRUE
;
1544 if (!c
->authorized
&&
1546 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
1548 pa_log_info("Client authenticated by IP ACL.");
1549 c
->authorized
= TRUE
;
1552 if (!c
->authorized
) {
1554 pa_gettimeofday(&tv
);
1555 tv
.tv_sec
+= AUTH_TIMEOUT
;
1556 c
->auth_timeout_event
= p
->core
->mainloop
->time_new(p
->core
->mainloop
, &tv
, 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
));