4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 #include <polyp/sample.h>
34 #include <polypcore/esound.h>
35 #include <polypcore/memblock.h>
36 #include <polypcore/client.h>
37 #include <polypcore/sink-input.h>
38 #include <polypcore/sink.h>
39 #include <polypcore/source-output.h>
40 #include <polypcore/source.h>
41 #include <polypcore/core-scache.h>
42 #include <polypcore/sample-util.h>
43 #include <polypcore/authkey.h>
44 #include <polypcore/namereg.h>
45 #include <polypcore/xmalloc.h>
46 #include <polypcore/log.h>
47 #include <polypcore/util.h>
48 #include <polypcore/utf8.h>
50 #include "endianmacros.h"
52 #include "protocol-esound.h"
54 /* Don't accept more connection than this */
55 #define MAX_CONNECTIONS 10
57 /* Kick a client if it doesn't authenticate within this time */
58 #define AUTH_TIMEOUT 5
60 #define DEFAULT_COOKIE_FILE ".esd_auth"
62 #define PLAYBACK_BUFFER_SECONDS (.25)
63 #define PLAYBACK_BUFFER_FRAGMENTS (10)
64 #define RECORD_BUFFER_SECONDS (5)
65 #define RECORD_BUFFER_FRAGMENTS (100)
67 #define MAX_CACHE_SAMPLE_SIZE (1024000)
69 #define SCACHE_PREFIX "esound."
71 /* This is heavily based on esound's code */
76 pa_protocol_esound
*protocol
;
79 int authorized
, swap_byte_order
;
81 size_t write_data_alloc
, write_data_index
, write_data_length
;
83 size_t read_data_alloc
, read_data_length
;
85 esd_client_state_t state
;
86 pa_sink_input
*sink_input
;
87 pa_source_output
*source_output
;
88 pa_memblockq
*input_memblockq
, *output_memblockq
;
89 pa_defer_event
*defer_event
;
92 pa_memblock
*current_memblock
;
93 size_t memblock_index
, fragment_size
;
99 pa_sample_spec sample_spec
;
102 pa_time_event
*auth_timeout_event
;
105 struct pa_protocol_esound
{
109 pa_socket_server
*server
;
110 pa_idxset
*connections
;
111 char *sink_name
, *source_name
;
113 uint8_t esd_key
[ESD_KEY_LEN
];
116 typedef struct proto_handler
{
118 int (*proc
)(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
119 const char *description
;
120 } esd_proto_handler_info_t
;
122 static void sink_input_drop_cb(pa_sink_input
*i
, const pa_memchunk
*chunk
, size_t length
);
123 static int sink_input_peek_cb(pa_sink_input
*i
, pa_memchunk
*chunk
);
124 static void sink_input_kill_cb(pa_sink_input
*i
);
125 static pa_usec_t
sink_input_get_latency_cb(pa_sink_input
*i
);
126 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
128 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
129 static void source_output_kill_cb(pa_source_output
*o
);
131 static int esd_proto_connect(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
132 static int esd_proto_stream_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
133 static int esd_proto_stream_record(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
134 static int esd_proto_get_latency(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
135 static int esd_proto_server_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
136 static int esd_proto_all_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
137 static int esd_proto_stream_pan(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
138 static int esd_proto_sample_cache(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
139 static int esd_proto_sample_free_or_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
140 static int esd_proto_sample_get_id(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
141 static int esd_proto_standby_or_resume(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
143 /* the big map of protocol handler info */
144 static struct proto_handler proto_map
[ESD_PROTO_MAX
] = {
145 { ESD_KEY_LEN
+ sizeof(int), esd_proto_connect
, "connect" },
146 { ESD_KEY_LEN
+ sizeof(int), NULL
, "lock" },
147 { ESD_KEY_LEN
+ sizeof(int), NULL
, "unlock" },
149 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_play
, "stream play" },
150 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream rec" },
151 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream mon" },
153 { ESD_NAME_MAX
+ 3 * sizeof(int), esd_proto_sample_cache
, "sample cache" }, /* 6 */
154 { sizeof(int), esd_proto_sample_free_or_play
, "sample free" },
155 { sizeof(int), esd_proto_sample_free_or_play
, "sample play" }, /* 8 */
156 { sizeof(int), NULL
, "sample loop" },
157 { sizeof(int), NULL
, "sample stop" },
158 { -1, NULL
, "TODO: sample kill" },
160 { ESD_KEY_LEN
+ sizeof(int), esd_proto_standby_or_resume
, "standby" }, /* NOOP! */
161 { ESD_KEY_LEN
+ sizeof(int), esd_proto_standby_or_resume
, "resume" }, /* NOOP! */ /* 13 */
163 { ESD_NAME_MAX
, esd_proto_sample_get_id
, "sample getid" }, /* 14 */
164 { ESD_NAME_MAX
+ 2 * sizeof(int), NULL
, "stream filter" },
166 { sizeof(int), esd_proto_server_info
, "server info" },
167 { sizeof(int), esd_proto_all_info
, "all info" },
168 { -1, NULL
, "TODO: subscribe" },
169 { -1, NULL
, "TODO: unsubscribe" },
171 { 3 * sizeof(int), esd_proto_stream_pan
, "stream pan"},
172 { 3 * sizeof(int), NULL
, "sample pan" },
174 { sizeof(int), NULL
, "standby mode" },
175 { 0, esd_proto_get_latency
, "get latency" }
179 static void connection_free(struct connection
*c
) {
181 pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
);
183 if (c
->state
== ESD_STREAMING_DATA
)
184 c
->protocol
->n_player
--;
186 pa_client_free(c
->client
);
189 pa_sink_input_disconnect(c
->sink_input
);
190 pa_sink_input_unref(c
->sink_input
);
193 if (c
->source_output
) {
194 pa_source_output_disconnect(c
->source_output
);
195 pa_source_output_unref(c
->source_output
);
198 if (c
->input_memblockq
)
199 pa_memblockq_free(c
->input_memblockq
);
200 if (c
->output_memblockq
)
201 pa_memblockq_free(c
->output_memblockq
);
203 if (c
->playback
.current_memblock
)
204 pa_memblock_unref(c
->playback
.current_memblock
);
206 pa_xfree(c
->read_data
);
207 pa_xfree(c
->write_data
);
210 pa_iochannel_free(c
->io
);
213 c
->protocol
->core
->mainloop
->defer_free(c
->defer_event
);
215 if (c
->scache
.memchunk
.memblock
)
216 pa_memblock_unref(c
->scache
.memchunk
.memblock
);
217 pa_xfree(c
->scache
.name
);
219 if (c
->auth_timeout_event
)
220 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
225 static void connection_write_prepare(struct connection
*c
, size_t length
) {
229 t
= c
->write_data_length
+length
;
231 if (c
->write_data_alloc
< t
)
232 c
->write_data
= pa_xrealloc(c
->write_data
, c
->write_data_alloc
= t
);
234 assert(c
->write_data
);
237 static void connection_write(struct connection
*c
, const void *data
, size_t length
) {
241 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->defer_enable
);
242 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
244 connection_write_prepare(c
, length
);
246 assert(c
->write_data
);
248 i
= c
->write_data_length
;
249 c
->write_data_length
+= length
;
251 memcpy((char*)c
->write_data
+ i
, data
, length
);
254 static void format_esd2native(int format
, int swap_bytes
, pa_sample_spec
*ss
) {
257 ss
->channels
= ((format
& ESD_MASK_CHAN
) == ESD_STEREO
) ? 2 : 1;
258 if ((format
& ESD_MASK_BITS
) == ESD_BITS16
)
259 ss
->format
= swap_bytes
? PA_SAMPLE_S16RE
: PA_SAMPLE_S16NE
;
261 ss
->format
= PA_SAMPLE_U8
;
264 static int format_native2esd(pa_sample_spec
*ss
) {
267 format
= (ss
->format
== PA_SAMPLE_U8
) ? ESD_BITS8
: ESD_BITS16
;
268 format
|= (ss
->channels
>= 2) ? ESD_STEREO
: ESD_MONO
;
273 #define CHECK_VALIDITY(expression, string) do { \
274 if (!(expression)) { \
275 pa_log_warn(__FILE__ ": " string); \
280 /*** esound commands ***/
282 static int esd_proto_connect(struct connection
*c
, PA_GCC_UNUSED esd_proto_t request
, const void *data
, size_t length
) {
286 assert(length
== (ESD_KEY_LEN
+ sizeof(uint32_t)));
288 if (!c
->authorized
) {
289 if (memcmp(data
, c
->protocol
->esd_key
, ESD_KEY_LEN
) != 0) {
290 pa_log(__FILE__
": kicked client with invalid authorization key.");
295 if (c
->auth_timeout_event
) {
296 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
297 c
->auth_timeout_event
= NULL
;
301 data
= (const char*)data
+ ESD_KEY_LEN
;
303 memcpy(&ekey
, data
, sizeof(uint32_t));
304 if (ekey
== ESD_ENDIAN_KEY
)
305 c
->swap_byte_order
= 0;
306 else if (ekey
== ESD_SWAP_ENDIAN_KEY
)
307 c
->swap_byte_order
= 1;
309 pa_log(__FILE__
": client sent invalid endian key");
314 connection_write(c
, &ok
, sizeof(int));
318 static int esd_proto_stream_play(struct connection
*c
, PA_GCC_UNUSED esd_proto_t request
, const void *data
, size_t length
) {
319 char name
[ESD_NAME_MAX
];
320 int32_t format
, rate
;
325 assert(c
&& length
== (sizeof(int32_t)*2+ESD_NAME_MAX
));
327 memcpy(&format
, data
, sizeof(int32_t));
328 format
= MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
329 data
= (const char*)data
+ sizeof(int32_t);
331 memcpy(&rate
, data
, sizeof(int32_t));
332 rate
= MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
333 data
= (const char*)data
+ sizeof(int32_t);
336 format_esd2native(format
, c
->swap_byte_order
, &ss
);
338 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification");
339 sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1);
340 CHECK_VALIDITY(sink
, "No such sink");
342 strncpy(name
, data
, sizeof(name
));
343 name
[sizeof(name
)-1] = 0;
345 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in stream name");
347 pa_client_set_name(c
->client
, name
);
349 assert(!c
->sink_input
&& !c
->input_memblockq
);
351 c
->sink_input
= pa_sink_input_new(sink
, __FILE__
, name
, &ss
, NULL
, NULL
, 0, -1);
353 CHECK_VALIDITY(c
->sink_input
, "Failed to create sink input.");
355 l
= (size_t) (pa_bytes_per_second(&ss
)*PLAYBACK_BUFFER_SECONDS
);
356 c
->input_memblockq
= pa_memblockq_new(
362 l
/PLAYBACK_BUFFER_FRAGMENTS
,
364 c
->protocol
->core
->memblock_stat
);
365 pa_iochannel_socket_set_rcvbuf(c
->io
, l
/PLAYBACK_BUFFER_FRAGMENTS
*2);
366 c
->playback
.fragment_size
= l
/10;
368 c
->sink_input
->owner
= c
->protocol
->module
;
369 c
->sink_input
->client
= c
->client
;
370 c
->sink_input
->peek
= sink_input_peek_cb
;
371 c
->sink_input
->drop
= sink_input_drop_cb
;
372 c
->sink_input
->kill
= sink_input_kill_cb
;
373 c
->sink_input
->get_latency
= sink_input_get_latency_cb
;
374 c
->sink_input
->userdata
= c
;
376 c
->state
= ESD_STREAMING_DATA
;
378 c
->protocol
->n_player
++;
383 static int esd_proto_stream_record(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
384 char name
[ESD_NAME_MAX
];
385 int32_t format
, rate
;
390 assert(c
&& length
== (sizeof(int32_t)*2+ESD_NAME_MAX
));
392 memcpy(&format
, data
, sizeof(int32_t));
393 format
= MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
394 data
= (const char*)data
+ sizeof(int32_t);
396 memcpy(&rate
, data
, sizeof(int32_t));
397 rate
= MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
398 data
= (const char*)data
+ sizeof(int32_t);
401 format_esd2native(format
, c
->swap_byte_order
, &ss
);
403 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification.");
405 if (request
== ESD_PROTO_STREAM_MON
) {
408 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1))) {
409 pa_log(__FILE__
": no such sink.");
413 if (!(source
= sink
->monitor_source
)) {
414 pa_log(__FILE__
": no such monitor source.");
418 assert(request
== ESD_PROTO_STREAM_REC
);
420 if (!(source
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->source_name
, PA_NAMEREG_SOURCE
, 1))) {
421 pa_log(__FILE__
": no such source.");
426 strncpy(name
, data
, sizeof(name
));
427 name
[sizeof(name
)-1] = 0;
429 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in stream name.");
431 pa_client_set_name(c
->client
, name
);
433 assert(!c
->output_memblockq
&& !c
->source_output
);
435 if (!(c
->source_output
= pa_source_output_new(source
, __FILE__
, name
, &ss
, NULL
, -1))) {
436 pa_log(__FILE__
": failed to create source output");
440 l
= (size_t) (pa_bytes_per_second(&ss
)*RECORD_BUFFER_SECONDS
);
441 c
->output_memblockq
= pa_memblockq_new(
449 c
->protocol
->core
->memblock_stat
);
450 pa_iochannel_socket_set_sndbuf(c
->io
, l
/RECORD_BUFFER_FRAGMENTS
*2);
452 c
->source_output
->owner
= c
->protocol
->module
;
453 c
->source_output
->client
= c
->client
;
454 c
->source_output
->push
= source_output_push_cb
;
455 c
->source_output
->kill
= source_output_kill_cb
;
456 c
->source_output
->get_latency
= source_output_get_latency_cb
;
457 c
->source_output
->userdata
= c
;
459 c
->state
= ESD_STREAMING_DATA
;
461 c
->protocol
->n_player
++;
466 static int esd_proto_get_latency(struct connection
*c
, PA_GCC_UNUSED esd_proto_t request
, const void *data
, size_t length
) {
470 assert(c
&& !data
&& length
== 0);
472 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1)))
475 double usec
= pa_sink_get_latency(sink
);
476 latency
= (int) ((usec
*44100)/1000000);
479 latency
= MAYBE_INT32_SWAP(c
->swap_byte_order
, latency
);
480 connection_write(c
, &latency
, sizeof(int32_t));
484 static int esd_proto_server_info(struct connection
*c
, PA_GCC_UNUSED esd_proto_t request
, const void *data
, size_t length
) {
485 int32_t rate
= 44100, format
= ESD_STEREO
|ESD_BITS16
;
489 assert(c
&& data
&& length
== sizeof(int32_t));
491 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1))) {
492 rate
= sink
->sample_spec
.rate
;
493 format
= format_native2esd(&sink
->sample_spec
);
496 connection_write_prepare(c
, sizeof(int32_t) * 3);
499 connection_write(c
, &response
, sizeof(int32_t));
500 rate
= MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
501 connection_write(c
, &rate
, sizeof(int32_t));
502 format
= MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
503 connection_write(c
, &format
, sizeof(int32_t));
508 static int esd_proto_all_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
511 struct connection
*conn
;
512 uint32_t idx
= PA_IDXSET_INVALID
;
514 char terminator
[sizeof(int32_t)*6+ESD_NAME_MAX
];
516 assert(c
&& data
&& length
== sizeof(int32_t));
518 if (esd_proto_server_info(c
, request
, data
, length
) < 0)
521 k
= sizeof(int32_t)*5+ESD_NAME_MAX
;
522 s
= sizeof(int32_t)*6+ESD_NAME_MAX
;
523 nsamples
= c
->protocol
->core
->scache
? pa_idxset_size(c
->protocol
->core
->scache
) : 0;
524 t
= s
*(nsamples
+1) + k
*(c
->protocol
->n_player
+1);
526 connection_write_prepare(c
, t
);
528 memset(terminator
, 0, sizeof(terminator
));
530 for (conn
= pa_idxset_first(c
->protocol
->connections
, &idx
); conn
; conn
= pa_idxset_next(c
->protocol
->connections
, &idx
)) {
531 int32_t id
, format
= ESD_BITS16
| ESD_STEREO
, rate
= 44100, lvolume
= ESD_VOLUME_BASE
, rvolume
= ESD_VOLUME_BASE
;
532 char name
[ESD_NAME_MAX
];
534 if (conn
->state
!= ESD_STREAMING_DATA
)
539 if (conn
->sink_input
) {
540 pa_cvolume volume
= *pa_sink_input_get_volume(conn
->sink_input
);
541 rate
= conn
->sink_input
->sample_spec
.rate
;
542 lvolume
= (volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
;
543 rvolume
= (volume
.values
[1]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
;
544 format
= format_native2esd(&conn
->sink_input
->sample_spec
);
548 id
= MAYBE_INT32_SWAP(c
->swap_byte_order
, (int32_t) (conn
->index
+1));
549 connection_write(c
, &id
, sizeof(int32_t));
552 assert(conn
->client
);
553 strncpy(name
, conn
->client
->name
, ESD_NAME_MAX
);
554 connection_write(c
, name
, ESD_NAME_MAX
);
557 rate
= MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
558 connection_write(c
, &rate
, sizeof(int32_t));
561 lvolume
= MAYBE_INT32_SWAP(c
->swap_byte_order
, lvolume
);
562 connection_write(c
, &lvolume
, sizeof(int32_t));
565 rvolume
= MAYBE_INT32_SWAP(c
->swap_byte_order
, rvolume
);
566 connection_write(c
, &rvolume
, sizeof(int32_t));
569 format
= MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
570 connection_write(c
, &format
, sizeof(int32_t));
575 assert(t
== s
*(nsamples
+1)+k
);
579 connection_write(c
, terminator
, k
);
584 idx
= PA_IDXSET_INVALID
;
585 for (ce
= pa_idxset_first(c
->protocol
->core
->scache
, &idx
); ce
; ce
= pa_idxset_next(c
->protocol
->core
->scache
, &idx
)) {
586 int32_t id
, rate
, lvolume
, rvolume
, format
, len
;
587 char name
[ESD_NAME_MAX
];
592 id
= MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) (ce
->index
+1));
593 connection_write(c
, &id
, sizeof(int32_t));
596 if (strncmp(ce
->name
, SCACHE_PREFIX
, sizeof(SCACHE_PREFIX
)-1) == 0)
597 strncpy(name
, ce
->name
+sizeof(SCACHE_PREFIX
)-1, ESD_NAME_MAX
);
599 snprintf(name
, ESD_NAME_MAX
, "native.%s", ce
->name
);
600 connection_write(c
, name
, ESD_NAME_MAX
);
603 rate
= MAYBE_UINT32_SWAP(c
->swap_byte_order
, ce
->sample_spec
.rate
);
604 connection_write(c
, &rate
, sizeof(int32_t));
607 lvolume
= MAYBE_UINT32_SWAP(c
->swap_byte_order
, (ce
->volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
608 connection_write(c
, &lvolume
, sizeof(int32_t));
611 rvolume
= MAYBE_UINT32_SWAP(c
->swap_byte_order
, (ce
->volume
.values
[0]*ESD_VOLUME_BASE
)/PA_VOLUME_NORM
);
612 connection_write(c
, &rvolume
, sizeof(int32_t));
615 format
= MAYBE_INT32_SWAP(c
->swap_byte_order
, format_native2esd(&ce
->sample_spec
));
616 connection_write(c
, &format
, sizeof(int32_t));
619 len
= MAYBE_INT32_SWAP(c
->swap_byte_order
, (int) ce
->memchunk
.length
);
620 connection_write(c
, &len
, sizeof(int32_t));
628 connection_write(c
, terminator
, s
);
633 static int esd_proto_stream_pan(struct connection
*c
, PA_GCC_UNUSED esd_proto_t request
, const void *data
, size_t length
) {
635 uint32_t idx
, lvolume
, rvolume
;
636 struct connection
*conn
;
638 assert(c
&& data
&& length
== sizeof(int32_t)*3);
640 memcpy(&idx
, data
, sizeof(uint32_t));
641 idx
= MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
642 data
= (const char*)data
+ sizeof(uint32_t);
644 memcpy(&lvolume
, data
, sizeof(uint32_t));
645 lvolume
= MAYBE_UINT32_SWAP(c
->swap_byte_order
, lvolume
);
646 data
= (const char*)data
+ sizeof(uint32_t);
648 memcpy(&rvolume
, data
, sizeof(uint32_t));
649 rvolume
= MAYBE_UINT32_SWAP(c
->swap_byte_order
, rvolume
);
650 data
= (const char*)data
+ sizeof(uint32_t);
652 if ((conn
= pa_idxset_get_by_index(c
->protocol
->connections
, idx
)) && conn
->sink_input
) {
654 volume
.values
[0] = (lvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
655 volume
.values
[1] = (rvolume
*PA_VOLUME_NORM
)/ESD_VOLUME_BASE
;
657 pa_sink_input_set_volume(conn
->sink_input
, &volume
);
662 connection_write(c
, &ok
, sizeof(int32_t));
667 static int esd_proto_sample_cache(struct connection
*c
, PA_GCC_UNUSED esd_proto_t request
, const void *data
, size_t length
) {
669 int32_t format
, rate
, sc_length
;
671 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
673 assert(c
&& data
&& length
== (ESD_NAME_MAX
+3*sizeof(int32_t)));
675 memcpy(&format
, data
, sizeof(int32_t));
676 format
= MAYBE_INT32_SWAP(c
->swap_byte_order
, format
);
677 data
= (const char*)data
+ sizeof(int32_t);
679 memcpy(&rate
, data
, sizeof(int32_t));
680 rate
= MAYBE_INT32_SWAP(c
->swap_byte_order
, rate
);
681 data
= (const char*)data
+ sizeof(int32_t);
684 format_esd2native(format
, c
->swap_byte_order
, &ss
);
686 CHECK_VALIDITY(pa_sample_spec_valid(&ss
), "Invalid sample specification.");
688 memcpy(&sc_length
, data
, sizeof(int32_t));
689 sc_length
= MAYBE_INT32_SWAP(c
->swap_byte_order
, sc_length
);
690 data
= (const char*)data
+ sizeof(int32_t);
692 CHECK_VALIDITY(sc_length
<= MAX_CACHE_SAMPLE_SIZE
, "Sample too large.");
694 strcpy(name
, SCACHE_PREFIX
);
695 strncpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
696 name
[sizeof(name
)-1] = 0;
698 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in sample name.");
700 assert(!c
->scache
.memchunk
.memblock
);
701 c
->scache
.memchunk
.memblock
= pa_memblock_new(sc_length
, c
->protocol
->core
->memblock_stat
);
702 c
->scache
.memchunk
.index
= 0;
703 c
->scache
.memchunk
.length
= sc_length
;
704 c
->scache
.sample_spec
= ss
;
705 assert(!c
->scache
.name
);
706 c
->scache
.name
= pa_xstrdup(name
);
708 c
->state
= ESD_CACHING_SAMPLE
;
710 pa_scache_add_item(c
->protocol
->core
, c
->scache
.name
, NULL
, NULL
, NULL
, &idx
);
713 connection_write(c
, &idx
, sizeof(uint32_t));
718 static int esd_proto_sample_get_id(struct connection
*c
, PA_GCC_UNUSED esd_proto_t request
, const void *data
, size_t length
) {
721 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
723 assert(c
&& data
&& length
== ESD_NAME_MAX
);
725 strcpy(name
, SCACHE_PREFIX
);
726 strncpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
727 name
[sizeof(name
)-1] = 0;
729 CHECK_VALIDITY(pa_utf8_valid(name
), "Invalid UTF8 in sample name.");
732 if ((idx
= pa_scache_get_id_by_name(c
->protocol
->core
, name
)) != PA_IDXSET_INVALID
)
735 connection_write(c
, &ok
, sizeof(int32_t));
740 static int esd_proto_sample_free_or_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
745 assert(c
&& data
&& length
== sizeof(int32_t));
747 memcpy(&idx
, data
, sizeof(uint32_t));
748 idx
= MAYBE_UINT32_SWAP(c
->swap_byte_order
, idx
) - 1;
752 if ((name
= pa_scache_get_name_by_id(c
->protocol
->core
, idx
))) {
753 if (request
== ESD_PROTO_SAMPLE_PLAY
) {
756 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1)))
757 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, PA_VOLUME_NORM
) >= 0)
760 assert(request
== ESD_PROTO_SAMPLE_FREE
);
762 if (pa_scache_remove_item(c
->protocol
->core
, name
) >= 0)
767 connection_write(c
, &ok
, sizeof(int32_t));
772 static int esd_proto_standby_or_resume(struct connection
*c
, PA_GCC_UNUSED esd_proto_t request
, PA_GCC_UNUSED
const void *data
, PA_GCC_UNUSED
size_t length
) {
775 connection_write_prepare(c
, sizeof(int32_t) * 2);
778 connection_write(c
, &ok
, sizeof(int32_t));
779 connection_write(c
, &ok
, sizeof(int32_t));
784 /*** client callbacks ***/
786 static void client_kill_cb(pa_client
*c
) {
787 assert(c
&& c
->userdata
);
788 connection_free(c
->userdata
);
791 /*** pa_iochannel callbacks ***/
793 static int do_read(struct connection
*c
) {
796 /* pa_log("READ"); */
798 if (c
->state
== ESD_NEXT_REQUEST
) {
800 assert(c
->read_data_length
< sizeof(c
->request
));
802 if ((r
= pa_iochannel_read(c
->io
, ((uint8_t*) &c
->request
) + c
->read_data_length
, sizeof(c
->request
) - c
->read_data_length
)) <= 0) {
803 pa_log_debug(__FILE__
": read() failed: %s", r
< 0 ? strerror(errno
) : "EOF");
807 if ((c
->read_data_length
+= r
) >= sizeof(c
->request
)) {
808 struct proto_handler
*handler
;
810 c
->request
= MAYBE_INT32_SWAP(c
->swap_byte_order
, c
->request
);
812 if (c
->request
< ESD_PROTO_CONNECT
|| c
->request
> ESD_PROTO_MAX
) {
813 pa_log(__FILE__
": recieved invalid request.");
817 handler
= proto_map
+c
->request
;
819 /* pa_log(__FILE__": executing request #%u", c->request); */
821 if (!handler
->proc
) {
822 pa_log(__FILE__
": recieved unimplemented request #%u.", c
->request
);
826 if (handler
->data_length
== 0) {
827 c
->read_data_length
= 0;
829 if (handler
->proc(c
, c
->request
, NULL
, 0) < 0)
833 if (c
->read_data_alloc
< handler
->data_length
)
834 c
->read_data
= pa_xrealloc(c
->read_data
, c
->read_data_alloc
= handler
->data_length
);
835 assert(c
->read_data
);
837 c
->state
= ESD_NEEDS_REQDATA
;
838 c
->read_data_length
= 0;
842 } else if (c
->state
== ESD_NEEDS_REQDATA
) {
844 struct proto_handler
*handler
= proto_map
+c
->request
;
846 assert(handler
->proc
);
848 assert(c
->read_data
&& c
->read_data_length
< handler
->data_length
);
850 if ((r
= pa_iochannel_read(c
->io
, (uint8_t*) c
->read_data
+ c
->read_data_length
, handler
->data_length
- c
->read_data_length
)) <= 0) {
851 pa_log_debug(__FILE__
": read() failed: %s", r
< 0 ? strerror(errno
) : "EOF");
855 if ((c
->read_data_length
+= r
) >= handler
->data_length
) {
856 size_t l
= c
->read_data_length
;
857 assert(handler
->proc
);
859 c
->state
= ESD_NEXT_REQUEST
;
860 c
->read_data_length
= 0;
862 if (handler
->proc(c
, c
->request
, c
->read_data
, l
) < 0)
865 } else if (c
->state
== ESD_CACHING_SAMPLE
) {
868 assert(c
->scache
.memchunk
.memblock
&& c
->scache
.name
&& c
->scache
.memchunk
.index
< c
->scache
.memchunk
.length
);
870 if ((r
= pa_iochannel_read(c
->io
, (uint8_t*) c
->scache
.memchunk
.memblock
->data
+c
->scache
.memchunk
.index
, c
->scache
.memchunk
.length
-c
->scache
.memchunk
.index
)) <= 0) {
871 pa_log_debug(__FILE__
": read() failed: %s", r
< 0 ? strerror(errno
) : "EOF");
875 c
->scache
.memchunk
.index
+= r
;
876 assert(c
->scache
.memchunk
.index
<= c
->scache
.memchunk
.length
);
878 if (c
->scache
.memchunk
.index
== c
->scache
.memchunk
.length
) {
881 c
->scache
.memchunk
.index
= 0;
882 pa_scache_add_item(c
->protocol
->core
, c
->scache
.name
, &c
->scache
.sample_spec
, NULL
, &c
->scache
.memchunk
, &idx
);
884 pa_memblock_unref(c
->scache
.memchunk
.memblock
);
885 c
->scache
.memchunk
.memblock
= NULL
;
886 c
->scache
.memchunk
.index
= c
->scache
.memchunk
.length
= 0;
888 pa_xfree(c
->scache
.name
);
889 c
->scache
.name
= NULL
;
891 c
->state
= ESD_NEXT_REQUEST
;
894 connection_write(c
, &idx
, sizeof(uint32_t));
897 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
902 assert(c
->input_memblockq
);
904 /* pa_log("STREAMING_DATA"); */
906 if (!(l
= pa_memblockq_missing(c
->input_memblockq
)))
909 if (l
> c
->playback
.fragment_size
)
910 l
= c
->playback
.fragment_size
;
912 if (c
->playback
.current_memblock
)
913 if (c
->playback
.current_memblock
->length
- c
->playback
.memblock_index
< l
) {
914 pa_memblock_unref(c
->playback
.current_memblock
);
915 c
->playback
.current_memblock
= NULL
;
916 c
->playback
.memblock_index
= 0;
919 if (!c
->playback
.current_memblock
) {
920 c
->playback
.current_memblock
= pa_memblock_new(c
->playback
.fragment_size
*2, c
->protocol
->core
->memblock_stat
);
921 assert(c
->playback
.current_memblock
&& c
->playback
.current_memblock
->length
>= l
);
922 c
->playback
.memblock_index
= 0;
925 if ((r
= pa_iochannel_read(c
->io
, (uint8_t*) c
->playback
.current_memblock
->data
+c
->playback
.memblock_index
, l
)) <= 0) {
926 pa_log_debug(__FILE__
": read() failed: %s", r
< 0 ? strerror(errno
) : "EOF");
930 chunk
.memblock
= c
->playback
.current_memblock
;
931 chunk
.index
= c
->playback
.memblock_index
;
933 assert(chunk
.memblock
);
935 c
->playback
.memblock_index
+= r
;
937 assert(c
->input_memblockq
);
938 pa_memblockq_push_align(c
->input_memblockq
, &chunk
);
939 assert(c
->sink_input
);
940 pa_sink_notify(c
->sink_input
->sink
);
946 static int do_write(struct connection
*c
) {
949 /* pa_log("WRITE"); */
951 if (c
->write_data_length
) {
954 assert(c
->write_data_index
< c
->write_data_length
);
955 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) {
956 pa_log(__FILE__
": write() failed: %s", strerror(errno
));
960 if ((c
->write_data_index
+=r
) >= c
->write_data_length
)
961 c
->write_data_length
= c
->write_data_index
= 0;
963 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->source_output
) {
967 assert(c
->output_memblockq
);
968 if (pa_memblockq_peek(c
->output_memblockq
, &chunk
) < 0)
971 assert(chunk
.memblock
&& chunk
.length
);
973 if ((r
= pa_iochannel_write(c
->io
, (uint8_t*) chunk
.memblock
->data
+chunk
.index
, chunk
.length
)) < 0) {
974 pa_memblock_unref(chunk
.memblock
);
975 pa_log(__FILE__
": write(): %s", strerror(errno
));
979 pa_memblockq_drop(c
->output_memblockq
, &chunk
, r
);
980 pa_memblock_unref(chunk
.memblock
);
982 pa_source_notify(c
->source_output
->source
);
988 static void do_work(struct connection
*c
) {
991 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->defer_enable
);
992 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
997 if (pa_iochannel_is_readable(c
->io
)) {
1002 if (c
->state
== ESD_STREAMING_DATA
&& c
->source_output
&& pa_iochannel_is_hungup(c
->io
))
1003 /* In case we are in capture mode we will never call read()
1004 * on the socket, hence we need to detect the hangup manually
1005 * here, instead of simply waiting for read() to return 0. */
1008 if (pa_iochannel_is_writable(c
->io
))
1009 if (do_write(c
) < 0)
1016 if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
1019 pa_iochannel_free(c
->io
);
1022 pa_memblockq_prebuf_disable(c
->input_memblockq
);
1023 pa_sink_notify(c
->sink_input
->sink
);
1028 static void io_callback(pa_iochannel
*io
, void *userdata
) {
1029 struct connection
*c
= userdata
;
1030 assert(io
&& c
&& c
->io
== io
);
1035 /*** defer callback ***/
1037 static void defer_callback(pa_mainloop_api
*a
, pa_defer_event
*e
, void *userdata
) {
1038 struct connection
*c
= userdata
;
1039 assert(a
&& c
&& c
->defer_event
== e
);
1041 /* pa_log("DEFER"); */
1046 /*** sink_input callbacks ***/
1048 static int sink_input_peek_cb(pa_sink_input
*i
, pa_memchunk
*chunk
) {
1049 struct connection
*c
;
1050 assert(i
&& i
->userdata
&& chunk
);
1053 if (pa_memblockq_peek(c
->input_memblockq
, chunk
) < 0) {
1064 static void sink_input_drop_cb(pa_sink_input
*i
, const pa_memchunk
*chunk
, size_t length
) {
1065 struct connection
*c
= i
->userdata
;
1066 assert(i
&& c
&& length
);
1068 /* pa_log("DROP"); */
1070 pa_memblockq_drop(c
->input_memblockq
, chunk
, length
);
1073 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->defer_enable
);
1076 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
1078 /* assert(pa_memblockq_get_length(c->input_memblockq) > 2048); */
1081 static void sink_input_kill_cb(pa_sink_input
*i
) {
1082 assert(i
&& i
->userdata
);
1083 connection_free((struct connection
*) i
->userdata
);
1086 static pa_usec_t
sink_input_get_latency_cb(pa_sink_input
*i
) {
1087 struct connection
*c
= i
->userdata
;
1089 return pa_bytes_to_usec(pa_memblockq_get_length(c
->input_memblockq
), &c
->sink_input
->sample_spec
);
1092 /*** source_output callbacks ***/
1094 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1095 struct connection
*c
= o
->userdata
;
1096 assert(o
&& c
&& chunk
);
1098 pa_memblockq_push(c
->output_memblockq
, chunk
);
1101 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->defer_enable
);
1104 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
1107 static void source_output_kill_cb(pa_source_output
*o
) {
1108 assert(o
&& o
->userdata
);
1109 connection_free((struct connection
*) o
->userdata
);
1112 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1113 struct connection
*c
= o
->userdata
;
1115 return pa_bytes_to_usec(pa_memblockq_get_length(c
->output_memblockq
), &c
->source_output
->sample_spec
);
1118 /*** socket server callback ***/
1120 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*tv
, void *userdata
) {
1121 struct connection
*c
= userdata
;
1122 assert(m
&& tv
&& c
&& c
->auth_timeout_event
== e
);
1128 static void on_connection(pa_socket_server
*s
, pa_iochannel
*io
, void *userdata
) {
1129 struct connection
*c
;
1130 pa_protocol_esound
*p
= userdata
;
1132 assert(s
&& io
&& p
);
1134 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
1135 pa_log(__FILE__
": Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
1136 pa_iochannel_free(io
);
1140 c
= pa_xnew(struct connection
, 1);
1143 pa_iochannel_set_callback(c
->io
, io_callback
, c
);
1145 pa_iochannel_socket_peer_to_string(io
, cname
, sizeof(cname
));
1147 c
->client
= pa_client_new(p
->core
, __FILE__
, cname
);
1149 c
->client
->owner
= p
->module
;
1150 c
->client
->kill
= client_kill_cb
;
1151 c
->client
->userdata
= c
;
1153 c
->authorized
= p
->public;
1154 c
->swap_byte_order
= 0;
1157 c
->read_data_length
= 0;
1158 c
->read_data
= pa_xmalloc(c
->read_data_alloc
= proto_map
[ESD_PROTO_CONNECT
].data_length
);
1160 c
->write_data_length
= c
->write_data_index
= c
->write_data_alloc
= 0;
1161 c
->write_data
= NULL
;
1163 c
->state
= ESD_NEEDS_REQDATA
;
1164 c
->request
= ESD_PROTO_CONNECT
;
1166 c
->sink_input
= NULL
;
1167 c
->input_memblockq
= NULL
;
1169 c
->source_output
= NULL
;
1170 c
->output_memblockq
= NULL
;
1172 c
->playback
.current_memblock
= NULL
;
1173 c
->playback
.memblock_index
= 0;
1174 c
->playback
.fragment_size
= 0;
1176 c
->scache
.memchunk
.length
= c
->scache
.memchunk
.index
= 0;
1177 c
->scache
.memchunk
.memblock
= NULL
;
1178 c
->scache
.name
= NULL
;
1180 if (!c
->authorized
) {
1182 pa_gettimeofday(&tv
);
1183 tv
.tv_sec
+= AUTH_TIMEOUT
;
1184 c
->auth_timeout_event
= p
->core
->mainloop
->time_new(p
->core
->mainloop
, &tv
, auth_timeout
, c
);
1186 c
->auth_timeout_event
= NULL
;
1188 c
->defer_event
= p
->core
->mainloop
->defer_new(p
->core
->mainloop
, defer_callback
, c
);
1189 assert(c
->defer_event
);
1190 p
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
1192 pa_idxset_put(p
->connections
, c
, &c
->index
);
1195 /*** entry points ***/
1197 pa_protocol_esound
* pa_protocol_esound_new(pa_core
*core
, pa_socket_server
*server
, pa_module
*m
, pa_modargs
*ma
) {
1198 pa_protocol_esound
*p
;
1200 assert(core
&& server
&& ma
);
1202 p
= pa_xnew(pa_protocol_esound
, 1);
1204 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &public) < 0) {
1205 pa_log(__FILE__
": auth-anonymous= expects a boolean argument.");
1209 if (pa_authkey_load_auto(pa_modargs_get_value(ma
, "cookie", DEFAULT_COOKIE_FILE
), p
->esd_key
, sizeof(p
->esd_key
)) < 0) {
1217 pa_socket_server_set_callback(p
->server
, on_connection
, p
);
1219 p
->connections
= pa_idxset_new(NULL
, NULL
);
1220 assert(p
->connections
);
1222 p
->sink_name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink", NULL
));
1223 p
->source_name
= pa_xstrdup(pa_modargs_get_value(ma
, "source", NULL
));
1229 void pa_protocol_esound_free(pa_protocol_esound
*p
) {
1230 struct connection
*c
;
1233 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
1236 pa_idxset_free(p
->connections
, NULL
, NULL
);
1237 pa_socket_server_unref(p
->server
);