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 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 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 "protocol-esound.h"
37 #include "sink-input.h"
39 #include "source-output.h"
43 #include "sample-util.h"
49 #define DEFAULT_COOKIE_FILE ".esd_auth"
51 #define PLAYBACK_BUFFER_SECONDS (.5)
52 #define PLAYBACK_BUFFER_FRAGMENTS (10)
53 #define RECORD_BUFFER_SECONDS (5)
54 #define RECORD_BUFFER_FRAGMENTS (100)
56 #define MAX_CACHE_SAMPLE_SIZE (1024000)
58 #define SCACHE_PREFIX "esound."
60 /* This is heavily based on esound's code */
64 struct pa_protocol_esound
*protocol
;
65 struct pa_iochannel
*io
;
66 struct pa_client
*client
;
67 int authorized
, swap_byte_order
;
69 size_t write_data_alloc
, write_data_index
, write_data_length
;
71 size_t read_data_alloc
, read_data_length
;
73 esd_client_state_t state
;
74 struct pa_sink_input
*sink_input
;
75 struct pa_source_output
*source_output
;
76 struct pa_memblockq
*input_memblockq
, *output_memblockq
;
77 struct pa_defer_event
*defer_event
;
79 struct pa_memblock
*current_memblock
;
80 size_t memblock_index
, fragment_size
;
83 struct pa_memchunk scache_memchunk
;
85 struct pa_sample_spec scache_sample_spec
;
88 struct pa_protocol_esound
{
90 struct pa_module
*module
;
92 struct pa_socket_server
*server
;
93 struct pa_idxset
*connections
;
94 char *sink_name
, *source_name
;
96 uint8_t esd_key
[ESD_KEY_LEN
];
99 typedef struct proto_handler
{
101 int (*proc
)(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
102 const char *description
;
103 } esd_proto_handler_info_t
;
105 static void sink_input_drop_cb(struct pa_sink_input
*i
, size_t length
);
106 static int sink_input_peek_cb(struct pa_sink_input
*i
, struct pa_memchunk
*chunk
);
107 static void sink_input_kill_cb(struct pa_sink_input
*i
);
108 static uint32_t sink_input_get_latency_cb(struct pa_sink_input
*i
);
110 static void source_output_push_cb(struct pa_source_output
*o
, const struct pa_memchunk
*chunk
);
111 static void source_output_kill_cb(struct pa_source_output
*o
);
113 static int esd_proto_connect(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
114 static int esd_proto_stream_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
115 static int esd_proto_stream_record(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
116 static int esd_proto_get_latency(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
117 static int esd_proto_server_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
118 static int esd_proto_all_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
119 static int esd_proto_stream_pan(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
120 static int esd_proto_sample_cache(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
121 static int esd_proto_sample_free_or_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
122 static int esd_proto_sample_get_id(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
124 /* the big map of protocol handler info */
125 static struct proto_handler proto_map
[ESD_PROTO_MAX
] = {
126 { ESD_KEY_LEN
+ sizeof(int), esd_proto_connect
, "connect" },
127 { ESD_KEY_LEN
+ sizeof(int), NULL
, "lock" },
128 { ESD_KEY_LEN
+ sizeof(int), NULL
, "unlock" },
130 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_play
, "stream play" },
131 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream rec" },
132 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream mon" },
134 { ESD_NAME_MAX
+ 3 * sizeof(int), esd_proto_sample_cache
, "sample cache" },
135 { sizeof(int), esd_proto_sample_free_or_play
, "sample free" },
136 { sizeof(int), esd_proto_sample_free_or_play
, "sample play" },
137 { sizeof(int), NULL
, "sample loop" },
138 { sizeof(int), NULL
, "sample stop" },
139 { -1, NULL
, "TODO: sample kill" },
141 { ESD_KEY_LEN
+ sizeof(int), NULL
, "standby" },
142 { ESD_KEY_LEN
+ sizeof(int), NULL
, "resume" },
144 { ESD_NAME_MAX
, esd_proto_sample_get_id
, "sample getid" },
145 { ESD_NAME_MAX
+ 2 * sizeof(int), NULL
, "stream filter" },
147 { sizeof(int), esd_proto_server_info
, "server info" },
148 { sizeof(int), esd_proto_all_info
, "all info" },
149 { -1, NULL
, "TODO: subscribe" },
150 { -1, NULL
, "TODO: unsubscribe" },
152 { 3 * sizeof(int), esd_proto_stream_pan
, "stream pan"},
153 { 3 * sizeof(int), NULL
, "sample pan" },
155 { sizeof(int), NULL
, "standby mode" },
156 { 0, esd_proto_get_latency
, "get latency" }
160 static void connection_free(struct connection
*c
) {
162 pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
);
164 if (c
->state
== ESD_STREAMING_DATA
)
165 c
->protocol
->n_player
--;
167 pa_client_free(c
->client
);
170 pa_sink_input_free(c
->sink_input
);
171 if (c
->source_output
)
172 pa_source_output_free(c
->source_output
);
173 if (c
->input_memblockq
)
174 pa_memblockq_free(c
->input_memblockq
);
175 if (c
->output_memblockq
)
176 pa_memblockq_free(c
->output_memblockq
);
178 if (c
->playback
.current_memblock
)
179 pa_memblock_unref(c
->playback
.current_memblock
);
181 pa_xfree(c
->read_data
);
182 pa_xfree(c
->write_data
);
184 pa_iochannel_free(c
->io
);
187 c
->protocol
->core
->mainloop
->defer_free(c
->defer_event
);
189 if (c
->scache_memchunk
.memblock
)
190 pa_memblock_unref(c
->scache_memchunk
.memblock
);
191 pa_xfree(c
->scache_name
);
196 static void* connection_write(struct connection
*c
, size_t length
) {
200 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->defer_enable
);
201 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
203 t
= c
->write_data_length
+length
;
205 if (c
->write_data_alloc
< t
)
206 c
->write_data
= pa_xrealloc(c
->write_data
, c
->write_data_alloc
= t
);
208 assert(c
->write_data
);
210 i
= c
->write_data_length
;
211 c
->write_data_length
+= length
;
213 return c
->write_data
+i
;
216 static void format_esd2native(int format
, struct pa_sample_spec
*ss
) {
219 ss
->channels
= ((format
& ESD_MASK_CHAN
) == ESD_STEREO
) ? 2 : 1;
220 ss
->format
= ((format
& ESD_MASK_BITS
) == ESD_BITS16
) ? PA_SAMPLE_S16NE
: PA_SAMPLE_U8
;
223 static int format_native2esd(struct pa_sample_spec
*ss
) {
226 format
= (ss
->format
== PA_SAMPLE_U8
) ? ESD_BITS8
: ESD_BITS16
;
227 format
|= (ss
->channels
>= 2) ? ESD_STEREO
: ESD_MONO
;
232 /*** esound commands ***/
234 static int esd_proto_connect(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
237 assert(length
== (ESD_KEY_LEN
+ sizeof(uint32_t)));
239 if (!c
->authorized
) {
240 if (memcmp(data
, c
->protocol
->esd_key
, ESD_KEY_LEN
) != 0) {
241 fprintf(stderr
, __FILE__
": kicked client with invalid authorization key.\n");
248 ekey
= *(uint32_t*)(data
+ESD_KEY_LEN
);
249 if (ekey
== ESD_ENDIAN_KEY
)
250 c
->swap_byte_order
= 0;
251 else if (ekey
== ESD_SWAP_ENDIAN_KEY
)
252 c
->swap_byte_order
= 1;
254 fprintf(stderr
, __FILE__
": client sent invalid endian key\n");
258 ok
= connection_write(c
, sizeof(int));
264 static int esd_proto_stream_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
265 char name
[ESD_NAME_MAX
];
267 struct pa_sink
*sink
;
268 struct pa_sample_spec ss
;
270 assert(c
&& length
== (sizeof(int)*2+ESD_NAME_MAX
));
272 format
= maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
273 rate
= maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
276 format_esd2native(format
, &ss
);
278 if (!pa_sample_spec_valid(&ss
))
281 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1))) {
282 fprintf(stderr
, __FILE__
": No output sink\n");
286 strncpy(name
, data
+ sizeof(int)*2, sizeof(name
));
287 name
[sizeof(name
)-1] = 0;
289 pa_client_rename(c
->client
, name
);
291 assert(!c
->input_memblockq
);
293 l
= (size_t) (pa_bytes_per_second(&ss
)*PLAYBACK_BUFFER_SECONDS
);
294 c
->input_memblockq
= pa_memblockq_new(l
, 0, pa_frame_size(&ss
), l
/2, l
/PLAYBACK_BUFFER_FRAGMENTS
);
295 assert(c
->input_memblockq
);
296 pa_iochannel_socket_set_rcvbuf(c
->io
, l
/PLAYBACK_BUFFER_FRAGMENTS
*2);
297 c
->playback
.fragment_size
= l
/10;
299 assert(!c
->sink_input
);
300 c
->sink_input
= pa_sink_input_new(sink
, name
, &ss
);
301 assert(c
->sink_input
);
303 c
->sink_input
->owner
= c
->protocol
->module
;
304 c
->sink_input
->client
= c
->client
;
305 c
->sink_input
->peek
= sink_input_peek_cb
;
306 c
->sink_input
->drop
= sink_input_drop_cb
;
307 c
->sink_input
->kill
= sink_input_kill_cb
;
308 c
->sink_input
->get_latency
= sink_input_get_latency_cb
;
309 c
->sink_input
->userdata
= c
;
311 c
->state
= ESD_STREAMING_DATA
;
313 c
->protocol
->n_player
++;
318 static int esd_proto_stream_record(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
319 char name
[ESD_NAME_MAX
];
321 struct pa_source
*source
;
322 struct pa_sample_spec ss
;
324 assert(c
&& length
== (sizeof(int)*2+ESD_NAME_MAX
));
326 format
= maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
327 rate
= maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
330 format_esd2native(format
, &ss
);
332 if (!pa_sample_spec_valid(&ss
))
335 if (request
== ESD_PROTO_STREAM_MON
) {
336 struct pa_sink
* sink
;
338 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1)))
341 if (!(source
= sink
->monitor_source
))
344 assert(request
== ESD_PROTO_STREAM_REC
);
346 if (!(source
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->source_name
, PA_NAMEREG_SOURCE
, 1)))
350 strncpy(name
, data
+ sizeof(int)*2, sizeof(name
));
351 name
[sizeof(name
)-1] = 0;
353 pa_client_rename(c
->client
, name
);
355 assert(!c
->output_memblockq
);
357 l
= (size_t) (pa_bytes_per_second(&ss
)*RECORD_BUFFER_SECONDS
);
358 c
->output_memblockq
= pa_memblockq_new(l
, 0, pa_frame_size(&ss
), 0, 0);
359 assert(c
->output_memblockq
);
360 pa_iochannel_socket_set_sndbuf(c
->io
, l
/RECORD_BUFFER_FRAGMENTS
*2);
362 assert(!c
->source_output
);
363 c
->source_output
= pa_source_output_new(source
, name
, &ss
);
364 assert(c
->source_output
);
366 c
->source_output
->owner
= c
->protocol
->module
;
367 c
->source_output
->client
= c
->client
;
368 c
->source_output
->push
= source_output_push_cb
;
369 c
->source_output
->kill
= source_output_kill_cb
;
370 c
->source_output
->userdata
= c
;
372 c
->state
= ESD_STREAMING_DATA
;
374 c
->protocol
->n_player
++;
379 static int esd_proto_get_latency(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
380 struct pa_sink
*sink
;
382 assert(c
&& !data
&& length
== 0);
384 if (!(sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1)))
387 float usec
= pa_sink_get_latency(sink
);
388 usec
+= PLAYBACK_BUFFER_SECONDS
*1000000; /* A better estimation would be a good idea! */
389 latency
= (int) ((usec
*44100)/1000000);
392 lag
= connection_write(c
, sizeof(int));
394 *lag
= c
->swap_byte_order
? swap_endian_32(latency
) : latency
;
398 static int esd_proto_server_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
399 int rate
= 44100, format
= ESD_STEREO
|ESD_BITS16
;
401 struct pa_sink
*sink
;
402 assert(c
&& data
&& length
== sizeof(int));
404 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1))) {
405 rate
= sink
->sample_spec
.rate
;
406 format
= format_native2esd(&sink
->sample_spec
);
409 response
= connection_write(c
, sizeof(int)*3);
412 *(response
++) = maybe_swap_endian_32(c
->swap_byte_order
, rate
);
413 *(response
++) = maybe_swap_endian_32(c
->swap_byte_order
, format
);
417 static int esd_proto_all_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
420 struct connection
*conn
;
421 size_t index
= PA_IDXSET_INVALID
;
423 assert(c
&& data
&& length
== sizeof(int));
425 if (esd_proto_server_info(c
, request
, data
, length
) < 0)
428 k
= sizeof(int)*5+ESD_NAME_MAX
;
429 s
= sizeof(int)*6+ESD_NAME_MAX
;
430 nsamples
= c
->protocol
->core
->scache_idxset
? pa_idxset_ncontents(c
->protocol
->core
->scache_idxset
) : 0;
431 response
= connection_write(c
, (t
= s
*(nsamples
+1) + k
*(c
->protocol
->n_player
+1)));
434 for (conn
= pa_idxset_first(c
->protocol
->connections
, &index
); conn
; conn
= pa_idxset_next(c
->protocol
->connections
, &index
)) {
435 int format
= ESD_BITS16
| ESD_STEREO
, rate
= 44100, volume
= 0xFF;
437 if (conn
->state
!= ESD_STREAMING_DATA
)
442 if (conn
->sink_input
) {
443 rate
= conn
->sink_input
->sample_spec
.rate
;
444 volume
= (conn
->sink_input
->volume
*0xFF)/0x100;
445 format
= format_native2esd(&conn
->sink_input
->sample_spec
);
449 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (int) (conn
->index
+1));
450 response
+= sizeof(int);
453 assert(conn
->client
);
454 strncpy(response
, conn
->client
->name
, ESD_NAME_MAX
);
455 response
+= ESD_NAME_MAX
;
458 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, rate
);
459 response
+= sizeof(int);
462 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, volume
);
463 response
+= sizeof(int);
466 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, volume
);
467 response
+= sizeof(int);
470 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, format
);
471 response
+= sizeof(int);
476 assert(t
== s
*(nsamples
+1)+k
);
477 memset(response
, 0, k
);
482 struct pa_scache_entry
*ce
;
484 index
= PA_IDXSET_INVALID
;
485 for (ce
= pa_idxset_first(c
->protocol
->core
->scache_idxset
, &index
); ce
; ce
= pa_idxset_next(c
->protocol
->core
->scache_idxset
, &index
)) {
489 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (int) (ce
->index
+1));
490 response
+= sizeof(int);
493 if (strncmp(ce
->name
, SCACHE_PREFIX
, sizeof(SCACHE_PREFIX
)-1) == 0)
494 strncpy(response
, ce
->name
+sizeof(SCACHE_PREFIX
)-1, ESD_NAME_MAX
);
496 snprintf(response
, ESD_NAME_MAX
, "native.%s", ce
->name
);
497 response
+= ESD_NAME_MAX
;
500 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, ce
->sample_spec
.rate
);
501 response
+= sizeof(int);
504 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (ce
->volume
*0xFF)/0x100);
505 response
+= sizeof(int);
508 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (ce
->volume
*0xFF)/0x100);
509 response
+= sizeof(int);
512 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, format_native2esd(&ce
->sample_spec
));
513 response
+= sizeof(int);
516 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (int) ce
->memchunk
.length
);
517 response
+= sizeof(int);
524 memset(response
, 0, s
);
529 static int esd_proto_stream_pan(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
531 uint32_t index
, volume
;
532 struct connection
*conn
;
533 assert(c
&& data
&& length
== sizeof(int)*3);
535 index
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
)-1;
536 volume
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
537 volume
= (volume
*0x100)/0xFF;
539 ok
= connection_write(c
, sizeof(int));
542 if ((conn
= pa_idxset_get_by_index(c
->protocol
->connections
, index
))) {
543 assert(conn
->sink_input
);
544 conn
->sink_input
->volume
= volume
;
552 static int esd_proto_sample_cache(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
553 struct pa_sample_spec ss
;
558 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
559 assert(c
&& data
&& length
== (ESD_NAME_MAX
+3*sizeof(int)));
561 format
= maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
562 rate
= maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
565 format_esd2native(format
, &ss
);
567 sc_length
= (size_t) maybe_swap_endian_32(c
->swap_byte_order
, (*((int*)data
+ 2)));
569 if (sc_length
>= MAX_CACHE_SAMPLE_SIZE
)
572 strcpy(name
, SCACHE_PREFIX
);
573 strncpy(name
+sizeof(SCACHE_PREFIX
)-1, data
+3*sizeof(int), ESD_NAME_MAX
);
574 name
[sizeof(name
)-1] = 0;
576 assert(!c
->scache_memchunk
.memblock
);
577 c
->scache_memchunk
.memblock
= pa_memblock_new(sc_length
);
578 c
->scache_memchunk
.index
= 0;
579 c
->scache_memchunk
.length
= sc_length
;
580 c
->scache_sample_spec
= ss
;
581 assert(!c
->scache_name
);
582 c
->scache_name
= pa_xstrdup(name
);
584 c
->state
= ESD_CACHING_SAMPLE
;
586 pa_scache_add_item(c
->protocol
->core
, c
->scache_name
, NULL
, NULL
, &index
);
588 ok
= connection_write(c
, sizeof(int));
596 static int esd_proto_sample_get_id(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
599 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
600 assert(c
&& data
&& length
== ESD_NAME_MAX
);
602 ok
= connection_write(c
, sizeof(int));
607 strcpy(name
, SCACHE_PREFIX
);
608 strncpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
609 name
[sizeof(name
)-1] = 0;
611 if ((index
= pa_scache_get_id_by_name(c
->protocol
->core
, name
)) != PA_IDXSET_INVALID
)
612 *ok
= (int) index
+1;
617 static int esd_proto_sample_free_or_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
621 assert(c
&& data
&& length
== sizeof(int));
623 index
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
)-1;
625 ok
= connection_write(c
, sizeof(int));
630 if ((name
= pa_scache_get_name_by_id(c
->protocol
->core
, index
))) {
631 if (request
== ESD_PROTO_SAMPLE_PLAY
) {
632 struct pa_sink
*sink
;
634 if ((sink
= pa_namereg_get(c
->protocol
->core
, c
->protocol
->sink_name
, PA_NAMEREG_SINK
, 1)))
635 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, PA_VOLUME_NORM
) >= 0)
638 assert(request
== ESD_PROTO_SAMPLE_FREE
);
640 if (pa_scache_remove_item(c
->protocol
->core
, name
) >= 0)
648 /*** client callbacks ***/
650 static void client_kill_cb(struct pa_client
*c
) {
651 assert(c
&& c
->userdata
);
652 connection_free(c
->userdata
);
655 /*** pa_iochannel callbacks ***/
657 static int do_read(struct connection
*c
) {
660 if (c
->state
== ESD_NEXT_REQUEST
) {
662 assert(c
->read_data_length
< sizeof(c
->request
));
664 if ((r
= pa_iochannel_read(c
->io
, ((void*) &c
->request
) + c
->read_data_length
, sizeof(c
->request
) - c
->read_data_length
)) <= 0) {
665 fprintf(stderr
, "protocol-esound.c: read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
669 if ((c
->read_data_length
+= r
) >= sizeof(c
->request
)) {
670 struct proto_handler
*handler
;
672 if (c
->swap_byte_order
)
673 c
->request
= swap_endian_32(c
->request
);
675 if (c
->request
< ESD_PROTO_CONNECT
|| c
->request
> ESD_PROTO_MAX
) {
676 fprintf(stderr
, "protocol-esound.c: recieved invalid request.\n");
680 handler
= proto_map
+c
->request
;
682 if (!handler
->proc
) {
683 fprintf(stderr
, "protocol-sound.c: recieved unimplemented request.\n");
687 if (handler
->data_length
== 0) {
688 c
->read_data_length
= 0;
690 if (handler
->proc(c
, c
->request
, NULL
, 0) < 0)
694 if (c
->read_data_alloc
< handler
->data_length
)
695 c
->read_data
= pa_xrealloc(c
->read_data
, c
->read_data_alloc
= handler
->data_length
);
696 assert(c
->read_data
);
698 c
->state
= ESD_NEEDS_REQDATA
;
699 c
->read_data_length
= 0;
703 } else if (c
->state
== ESD_NEEDS_REQDATA
) {
705 struct proto_handler
*handler
= proto_map
+c
->request
;
707 assert(handler
->proc
);
709 assert(c
->read_data
&& c
->read_data_length
< handler
->data_length
);
711 if ((r
= pa_iochannel_read(c
->io
, c
->read_data
+ c
->read_data_length
, handler
->data_length
- c
->read_data_length
)) <= 0) {
712 fprintf(stderr
, "protocol-esound.c: read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
716 if ((c
->read_data_length
+= r
) >= handler
->data_length
) {
717 size_t l
= c
->read_data_length
;
718 assert(handler
->proc
);
720 c
->state
= ESD_NEXT_REQUEST
;
721 c
->read_data_length
= 0;
723 if (handler
->proc(c
, c
->request
, c
->read_data
, l
) < 0)
726 } else if (c
->state
== ESD_CACHING_SAMPLE
) {
729 assert(c
->scache_memchunk
.memblock
&& c
->scache_name
&& c
->scache_memchunk
.index
< c
->scache_memchunk
.length
);
731 if ((r
= pa_iochannel_read(c
->io
, c
->scache_memchunk
.memblock
->data
+c
->scache_memchunk
.index
, c
->scache_memchunk
.length
-c
->scache_memchunk
.index
)) <= 0) {
732 fprintf(stderr
, __FILE__
": read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
736 c
->scache_memchunk
.index
+= r
;
737 assert(c
->scache_memchunk
.index
<= c
->scache_memchunk
.length
);
739 if (c
->scache_memchunk
.index
== c
->scache_memchunk
.length
) {
743 c
->scache_memchunk
.index
= 0;
744 pa_scache_add_item(c
->protocol
->core
, c
->scache_name
, &c
->scache_sample_spec
, &c
->scache_memchunk
, &index
);
746 pa_memblock_unref(c
->scache_memchunk
.memblock
);
747 c
->scache_memchunk
.memblock
= NULL
;
748 c
->scache_memchunk
.index
= c
->scache_memchunk
.length
= 0;
750 pa_xfree(c
->scache_name
);
751 c
->scache_name
= NULL
;
753 c
->state
= ESD_NEXT_REQUEST
;
755 ok
= connection_write(c
, sizeof(int));
760 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
761 struct pa_memchunk chunk
;
765 assert(c
->input_memblockq
);
767 if (!(l
= pa_memblockq_missing(c
->input_memblockq
)))
770 if (l
> c
->playback
.fragment_size
)
771 l
= c
->playback
.fragment_size
;
773 if (c
->playback
.current_memblock
)
774 if (c
->playback
.current_memblock
->length
- c
->playback
.memblock_index
< l
) {
775 pa_memblock_unref(c
->playback
.current_memblock
);
776 c
->playback
.current_memblock
= NULL
;
777 c
->playback
.memblock_index
= 0;
780 if (!c
->playback
.current_memblock
) {
781 c
->playback
.current_memblock
= pa_memblock_new(c
->playback
.fragment_size
*2);
782 assert(c
->playback
.current_memblock
&& c
->playback
.current_memblock
->length
>= l
);
783 c
->playback
.memblock_index
= 0;
786 if ((r
= pa_iochannel_read(c
->io
, c
->playback
.current_memblock
->data
+c
->playback
.memblock_index
, l
)) <= 0) {
787 fprintf(stderr
, __FILE__
": read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
791 chunk
.memblock
= c
->playback
.current_memblock
;
792 chunk
.index
= c
->playback
.memblock_index
;
794 assert(chunk
.memblock
);
796 c
->playback
.memblock_index
+= r
;
798 assert(c
->input_memblockq
);
799 pa_memblockq_push_align(c
->input_memblockq
, &chunk
, 0);
800 assert(c
->sink_input
);
801 pa_sink_notify(c
->sink_input
->sink
);
807 static int do_write(struct connection
*c
) {
810 if (c
->write_data_length
) {
813 assert(c
->write_data_index
< c
->write_data_length
);
814 if ((r
= pa_iochannel_write(c
->io
, c
->write_data
+c
->write_data_index
, c
->write_data_length
-c
->write_data_index
)) < 0) {
815 fprintf(stderr
, __FILE__
": write() failed: %s\n", strerror(errno
));
819 if ((c
->write_data_index
+=r
) >= c
->write_data_length
)
820 c
->write_data_length
= c
->write_data_index
= 0;
822 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->source_output
) {
823 struct pa_memchunk chunk
;
826 assert(c
->output_memblockq
);
827 if (pa_memblockq_peek(c
->output_memblockq
, &chunk
) < 0)
830 assert(chunk
.memblock
&& chunk
.length
);
832 if ((r
= pa_iochannel_write(c
->io
, chunk
.memblock
->data
+chunk
.index
, chunk
.length
)) < 0) {
833 pa_memblock_unref(chunk
.memblock
);
834 fprintf(stderr
, __FILE__
": write(): %s\n", strerror(errno
));
838 pa_memblockq_drop(c
->output_memblockq
, r
);
839 pa_memblock_unref(chunk
.memblock
);
845 static void do_work(struct connection
*c
) {
848 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->defer_enable
);
849 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
851 if (pa_iochannel_is_hungup(c
->io
))
854 if (pa_iochannel_is_writable(c
->io
))
858 if (pa_iochannel_is_readable(c
->io
))
868 static void io_callback(struct pa_iochannel
*io
, void *userdata
) {
869 struct connection
*c
= userdata
;
870 assert(io
&& c
&& c
->io
== io
);
875 /*** defer callback ***/
877 static void defer_callback(struct pa_mainloop_api
*a
, struct pa_defer_event
*e
, void *userdata
) {
878 struct connection
*c
= userdata
;
879 assert(a
&& c
&& c
->defer_event
== e
);
884 /*** sink_input callbacks ***/
886 static int sink_input_peek_cb(struct pa_sink_input
*i
, struct pa_memchunk
*chunk
) {
888 assert(i
&& i
->userdata
&& chunk
);
891 if (pa_memblockq_peek(c
->input_memblockq
, chunk
) < 0)
897 static void sink_input_drop_cb(struct pa_sink_input
*i
, size_t length
) {
898 struct connection
*c
= i
->userdata
;
899 assert(i
&& c
&& length
);
901 pa_memblockq_drop(c
->input_memblockq
, length
);
904 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->defer_enable
);
905 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
908 static void sink_input_kill_cb(struct pa_sink_input
*i
) {
909 assert(i
&& i
->userdata
);
910 connection_free((struct connection
*) i
->userdata
);
914 static uint32_t sink_input_get_latency_cb(struct pa_sink_input
*i
) {
915 struct connection
*c
= i
->userdata
;
917 return pa_bytes_to_usec(pa_memblockq_get_length(c
->input_memblockq
), &c
->sink_input
->sample_spec
);
920 /*** source_output callbacks ***/
922 static void source_output_push_cb(struct pa_source_output
*o
, const struct pa_memchunk
*chunk
) {
923 struct connection
*c
= o
->userdata
;
924 assert(o
&& c
&& chunk
);
926 pa_memblockq_push(c
->output_memblockq
, chunk
, 0);
929 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->defer_enable
);
930 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 1);
933 static void source_output_kill_cb(struct pa_source_output
*o
) {
934 assert(o
&& o
->userdata
);
935 connection_free((struct connection
*) o
->userdata
);
938 /*** socket server callback ***/
940 static void on_connection(struct pa_socket_server
*s
, struct pa_iochannel
*io
, void *userdata
) {
941 struct connection
*c
;
943 assert(s
&& io
&& userdata
);
945 c
= pa_xmalloc(sizeof(struct connection
));
946 c
->protocol
= userdata
;
948 pa_iochannel_set_callback(c
->io
, io_callback
, c
);
950 pa_iochannel_socket_peer_to_string(io
, cname
, sizeof(cname
));
951 assert(c
->protocol
->core
);
952 c
->client
= pa_client_new(c
->protocol
->core
, "ESOUND", cname
);
954 c
->client
->owner
= c
->protocol
->module
;
955 c
->client
->kill
= client_kill_cb
;
956 c
->client
->userdata
= c
;
958 c
->authorized
= c
->protocol
->public;
959 c
->swap_byte_order
= 0;
961 c
->read_data_length
= 0;
962 c
->read_data
= pa_xmalloc(c
->read_data_alloc
= proto_map
[ESD_PROTO_CONNECT
].data_length
);
964 c
->write_data_length
= c
->write_data_index
= c
->write_data_alloc
= 0;
965 c
->write_data
= NULL
;
967 c
->state
= ESD_NEEDS_REQDATA
;
968 c
->request
= ESD_PROTO_CONNECT
;
970 c
->sink_input
= NULL
;
971 c
->input_memblockq
= NULL
;
973 c
->source_output
= NULL
;
974 c
->output_memblockq
= NULL
;
976 c
->playback
.current_memblock
= NULL
;
977 c
->playback
.memblock_index
= 0;
978 c
->playback
.fragment_size
= 0;
980 c
->scache_memchunk
.length
= c
->scache_memchunk
.index
= 0;
981 c
->scache_memchunk
.memblock
= NULL
;
982 c
->scache_name
= NULL
;
984 c
->defer_event
= c
->protocol
->core
->mainloop
->defer_new(c
->protocol
->core
->mainloop
, defer_callback
, c
);
985 assert(c
->defer_event
);
986 c
->protocol
->core
->mainloop
->defer_enable(c
->defer_event
, 0);
988 pa_idxset_put(c
->protocol
->connections
, c
, &c
->index
);
991 /*** entry points ***/
993 struct pa_protocol_esound
* pa_protocol_esound_new(struct pa_core
*core
, struct pa_socket_server
*server
, struct pa_module
*m
, struct pa_modargs
*ma
) {
994 struct pa_protocol_esound
*p
;
995 assert(core
&& server
&& ma
);
997 p
= pa_xmalloc(sizeof(struct pa_protocol_esound
));
999 if (pa_authkey_load_auto(pa_modargs_get_value(ma
, "cookie", DEFAULT_COOKIE_FILE
), p
->esd_key
, sizeof(p
->esd_key
)) < 0) {
1007 pa_socket_server_set_callback(p
->server
, on_connection
, p
);
1009 p
->connections
= pa_idxset_new(NULL
, NULL
);
1010 assert(p
->connections
);
1012 p
->sink_name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink", NULL
));
1013 p
->source_name
= pa_xstrdup(pa_modargs_get_value(ma
, "source", NULL
));
1019 void pa_protocol_esound_free(struct pa_protocol_esound
*p
) {
1020 struct connection
*c
;
1023 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
1026 pa_idxset_free(p
->connections
, NULL
, NULL
);
1027 pa_socket_server_unref(p
->server
);