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"
47 #define DEFAULT_COOKIE_FILE ".esd_auth"
49 #define PLAYBACK_BUFFER_SECONDS (.5)
50 #define PLAYBACK_BUFFER_FRAGMENTS (10)
51 #define RECORD_BUFFER_SECONDS (5)
52 #define RECORD_BUFFER_FRAGMENTS (100)
54 #define MAX_CACHE_SAMPLE_SIZE (1024000)
56 #define SCACHE_PREFIX "esound."
58 /* This is heavily based on esound's code */
62 struct pa_protocol_esound
*protocol
;
63 struct pa_iochannel
*io
;
64 struct pa_client
*client
;
65 int authorized
, swap_byte_order
;
67 size_t write_data_alloc
, write_data_index
, write_data_length
;
69 size_t read_data_alloc
, read_data_length
;
71 esd_client_state_t state
;
72 struct pa_sink_input
*sink_input
;
73 struct pa_source_output
*source_output
;
74 struct pa_memblockq
*input_memblockq
, *output_memblockq
;
77 struct pa_memblock
*current_memblock
;
78 size_t memblock_index
, fragment_size
;
82 struct pa_memchunk scache_memchunk
;
84 struct pa_sample_spec scache_sample_spec
;
87 struct pa_protocol_esound
{
89 struct pa_module
*module
;
91 struct pa_socket_server
*server
;
92 struct pa_idxset
*connections
;
93 uint32_t sink_index
, source_index
;
95 uint8_t esd_key
[ESD_KEY_LEN
];
98 typedef struct proto_handler
{
100 int (*proc
)(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
101 const char *description
;
102 } esd_proto_handler_info_t
;
104 static void sink_input_drop_cb(struct pa_sink_input
*i
, size_t length
);
105 static int sink_input_peek_cb(struct pa_sink_input
*i
, struct pa_memchunk
*chunk
);
106 static void sink_input_kill_cb(struct pa_sink_input
*i
);
107 static uint32_t sink_input_get_latency_cb(struct pa_sink_input
*i
);
109 static void source_output_push_cb(struct pa_source_output
*o
, const struct pa_memchunk
*chunk
);
110 static void source_output_kill_cb(struct pa_source_output
*o
);
112 static int esd_proto_connect(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
113 static int esd_proto_stream_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
114 static int esd_proto_stream_record(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
115 static int esd_proto_get_latency(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
116 static int esd_proto_server_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
117 static int esd_proto_all_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
118 static int esd_proto_stream_pan(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
119 static int esd_proto_sample_cache(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
120 static int esd_proto_sample_free_or_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
121 static int esd_proto_sample_get_id(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
);
123 /* the big map of protocol handler info */
124 static struct proto_handler proto_map
[ESD_PROTO_MAX
] = {
125 { ESD_KEY_LEN
+ sizeof(int), esd_proto_connect
, "connect" },
126 { ESD_KEY_LEN
+ sizeof(int), NULL
, "lock" },
127 { ESD_KEY_LEN
+ sizeof(int), NULL
, "unlock" },
129 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_play
, "stream play" },
130 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream rec" },
131 { ESD_NAME_MAX
+ 2 * sizeof(int), esd_proto_stream_record
, "stream mon" },
133 { ESD_NAME_MAX
+ 3 * sizeof(int), esd_proto_sample_cache
, "sample cache" },
134 { sizeof(int), esd_proto_sample_free_or_play
, "sample free" },
135 { sizeof(int), esd_proto_sample_free_or_play
, "sample play" },
136 { sizeof(int), NULL
, "sample loop" },
137 { sizeof(int), NULL
, "sample stop" },
138 { -1, NULL
, "TODO: sample kill" },
140 { ESD_KEY_LEN
+ sizeof(int), NULL
, "standby" },
141 { ESD_KEY_LEN
+ sizeof(int), NULL
, "resume" },
143 { ESD_NAME_MAX
, esd_proto_sample_get_id
, "sample getid" },
144 { ESD_NAME_MAX
+ 2 * sizeof(int), NULL
, "stream filter" },
146 { sizeof(int), esd_proto_server_info
, "server info" },
147 { sizeof(int), esd_proto_all_info
, "all info" },
148 { -1, NULL
, "TODO: subscribe" },
149 { -1, NULL
, "TODO: unsubscribe" },
151 { 3 * sizeof(int), esd_proto_stream_pan
, "stream pan"},
152 { 3 * sizeof(int), NULL
, "sample pan" },
154 { sizeof(int), NULL
, "standby mode" },
155 { 0, esd_proto_get_latency
, "get latency" }
159 static void connection_free(struct connection
*c
) {
161 pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
);
163 if (c
->state
== ESD_STREAMING_DATA
)
164 c
->protocol
->n_player
--;
166 pa_client_free(c
->client
);
169 pa_sink_input_free(c
->sink_input
);
170 if (c
->source_output
)
171 pa_source_output_free(c
->source_output
);
172 if (c
->input_memblockq
)
173 pa_memblockq_free(c
->input_memblockq
);
174 if (c
->output_memblockq
)
175 pa_memblockq_free(c
->output_memblockq
);
177 if (c
->playback
.current_memblock
)
178 pa_memblock_unref(c
->playback
.current_memblock
);
183 pa_iochannel_free(c
->io
);
186 c
->protocol
->core
->mainloop
->cancel_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
);
188 if (c
->scache_memchunk
.memblock
)
189 pa_memblock_unref(c
->scache_memchunk
.memblock
);
190 free(c
->scache_name
);
195 static struct pa_sink
* get_output_sink(struct pa_protocol_esound
*p
) {
199 if (!(s
= pa_idxset_get_by_index(p
->core
->sinks
, p
->sink_index
)))
200 s
= pa_sink_get_default(p
->core
);
202 p
->sink_index
= s
? s
->index
: PA_IDXSET_INVALID
;
206 static struct pa_source
* get_input_source(struct pa_protocol_esound
*p
) {
210 if (!(s
= pa_idxset_get_by_index(p
->core
->sources
, p
->sink_index
)))
211 s
= pa_source_get_default(p
->core
);
213 p
->source_index
= s
? s
->index
: PA_IDXSET_INVALID
;
217 static void* connection_write(struct connection
*c
, size_t length
) {
221 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->enable_fixed
);
222 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 1);
224 t
= c
->write_data_length
+length
;
226 if (c
->write_data_alloc
< t
)
227 c
->write_data
= realloc(c
->write_data
, c
->write_data_alloc
= t
);
229 assert(c
->write_data
);
231 i
= c
->write_data_length
;
232 c
->write_data_length
+= length
;
234 return c
->write_data
+i
;
237 static void format_esd2native(int format
, struct pa_sample_spec
*ss
) {
240 ss
->channels
= ((format
& ESD_MASK_CHAN
) == ESD_STEREO
) ? 2 : 1;
241 ss
->format
= ((format
& ESD_MASK_BITS
) == ESD_BITS16
) ? PA_SAMPLE_S16NE
: PA_SAMPLE_U8
;
244 static int format_native2esd(struct pa_sample_spec
*ss
) {
247 format
= (ss
->format
== PA_SAMPLE_U8
) ? ESD_BITS8
: ESD_BITS16
;
248 format
|= (ss
->channels
>= 2) ? ESD_STEREO
: ESD_MONO
;
253 /*** esound commands ***/
255 static int esd_proto_connect(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
258 assert(length
== (ESD_KEY_LEN
+ sizeof(uint32_t)));
260 if (!c
->authorized
) {
261 if (memcmp(data
, c
->protocol
->esd_key
, ESD_KEY_LEN
) != 0) {
262 fprintf(stderr
, __FILE__
": kicked client with invalid authorization key.\n");
269 ekey
= *(uint32_t*)(data
+ESD_KEY_LEN
);
270 if (ekey
== ESD_ENDIAN_KEY
)
271 c
->swap_byte_order
= 0;
272 else if (ekey
== ESD_SWAP_ENDIAN_KEY
)
273 c
->swap_byte_order
= 1;
275 fprintf(stderr
, __FILE__
": client sent invalid endian key\n");
279 ok
= connection_write(c
, sizeof(int));
285 static int esd_proto_stream_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
286 char name
[ESD_NAME_MAX
];
288 struct pa_sink
*sink
;
289 struct pa_sample_spec ss
;
291 assert(c
&& length
== (sizeof(int)*2+ESD_NAME_MAX
));
293 format
= maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
294 rate
= maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
297 format_esd2native(format
, &ss
);
299 if (!pa_sample_spec_valid(&ss
))
302 if (!(sink
= get_output_sink(c
->protocol
))) {
303 fprintf(stderr
, __FILE__
": No output sink\n");
307 strncpy(name
, data
+ sizeof(int)*2, sizeof(name
));
308 name
[sizeof(name
)-1] = 0;
310 pa_client_rename(c
->client
, name
);
312 assert(!c
->input_memblockq
);
314 l
= (size_t) (pa_bytes_per_second(&ss
)*PLAYBACK_BUFFER_SECONDS
);
315 c
->input_memblockq
= pa_memblockq_new(l
, 0, pa_frame_size(&ss
), l
/2, l
/PLAYBACK_BUFFER_FRAGMENTS
);
316 assert(c
->input_memblockq
);
317 pa_iochannel_socket_set_rcvbuf(c
->io
, l
/PLAYBACK_BUFFER_FRAGMENTS
*2);
318 c
->playback
.fragment_size
= l
/10;
320 assert(!c
->sink_input
);
321 c
->sink_input
= pa_sink_input_new(sink
, name
, &ss
);
322 assert(c
->sink_input
);
324 c
->sink_input
->owner
= c
->protocol
->module
;
325 c
->sink_input
->client
= c
->client
;
326 c
->sink_input
->peek
= sink_input_peek_cb
;
327 c
->sink_input
->drop
= sink_input_drop_cb
;
328 c
->sink_input
->kill
= sink_input_kill_cb
;
329 c
->sink_input
->get_latency
= sink_input_get_latency_cb
;
330 c
->sink_input
->userdata
= c
;
332 c
->state
= ESD_STREAMING_DATA
;
334 c
->protocol
->n_player
++;
339 static int esd_proto_stream_record(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
340 char name
[ESD_NAME_MAX
];
342 struct pa_source
*source
;
343 struct pa_sample_spec ss
;
345 assert(c
&& length
== (sizeof(int)*2+ESD_NAME_MAX
));
347 format
= maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
348 rate
= maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
351 format_esd2native(format
, &ss
);
353 if (!pa_sample_spec_valid(&ss
))
356 if (request
== ESD_PROTO_STREAM_MON
) {
357 struct pa_sink
* sink
;
359 if (!(sink
= get_output_sink(c
->protocol
)))
362 if (!(source
= sink
->monitor_source
))
365 assert(request
== ESD_PROTO_STREAM_REC
);
367 if (!(source
= get_input_source(c
->protocol
)))
371 strncpy(name
, data
+ sizeof(int)*2, sizeof(name
));
372 name
[sizeof(name
)-1] = 0;
374 pa_client_rename(c
->client
, name
);
376 assert(!c
->output_memblockq
);
378 l
= (size_t) (pa_bytes_per_second(&ss
)*RECORD_BUFFER_SECONDS
);
379 c
->output_memblockq
= pa_memblockq_new(l
, 0, pa_frame_size(&ss
), 0, 0);
380 assert(c
->output_memblockq
);
381 pa_iochannel_socket_set_sndbuf(c
->io
, l
/RECORD_BUFFER_FRAGMENTS
*2);
383 assert(!c
->source_output
);
384 c
->source_output
= pa_source_output_new(source
, name
, &ss
);
385 assert(c
->source_output
);
387 c
->source_output
->owner
= c
->protocol
->module
;
388 c
->source_output
->client
= c
->client
;
389 c
->source_output
->push
= source_output_push_cb
;
390 c
->source_output
->kill
= source_output_kill_cb
;
391 c
->source_output
->userdata
= c
;
393 c
->state
= ESD_STREAMING_DATA
;
395 c
->protocol
->n_player
++;
400 static int esd_proto_get_latency(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
401 struct pa_sink
*sink
;
403 assert(c
&& !data
&& length
== 0);
405 if (!(sink
= get_output_sink(c
->protocol
)))
408 float usec
= pa_sink_get_latency(sink
);
409 usec
+= PLAYBACK_BUFFER_SECONDS
*1000000; /* A better estimation would be a good idea! */
410 latency
= (int) ((usec
*44100)/1000000);
413 lag
= connection_write(c
, sizeof(int));
415 *lag
= c
->swap_byte_order
? swap_endian_32(latency
) : latency
;
419 static int esd_proto_server_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
420 int rate
= 44100, format
= ESD_STEREO
|ESD_BITS16
;
422 struct pa_sink
*sink
;
423 assert(c
&& data
&& length
== sizeof(int));
425 if ((sink
= get_output_sink(c
->protocol
))) {
426 rate
= sink
->sample_spec
.rate
;
427 format
= format_native2esd(&sink
->sample_spec
);
430 response
= connection_write(c
, sizeof(int)*3);
433 *(response
++) = maybe_swap_endian_32(c
->swap_byte_order
, rate
);
434 *(response
++) = maybe_swap_endian_32(c
->swap_byte_order
, format
);
438 static int esd_proto_all_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
441 struct connection
*conn
;
442 size_t index
= PA_IDXSET_INVALID
;
444 assert(c
&& data
&& length
== sizeof(int));
446 if (esd_proto_server_info(c
, request
, data
, length
) < 0)
449 k
= sizeof(int)*5+ESD_NAME_MAX
;
450 s
= sizeof(int)*6+ESD_NAME_MAX
;
451 nsamples
= c
->protocol
->core
->scache_idxset
? pa_idxset_ncontents(c
->protocol
->core
->scache_idxset
) : 0;
452 response
= connection_write(c
, (t
= s
*(nsamples
+1) + k
*(c
->protocol
->n_player
+1)));
455 for (conn
= pa_idxset_first(c
->protocol
->connections
, &index
); conn
; conn
= pa_idxset_next(c
->protocol
->connections
, &index
)) {
456 int format
= ESD_BITS16
| ESD_STEREO
, rate
= 44100, volume
= 0xFF;
458 if (conn
->state
!= ESD_STREAMING_DATA
)
463 if (conn
->sink_input
) {
464 rate
= conn
->sink_input
->sample_spec
.rate
;
465 volume
= (conn
->sink_input
->volume
*0xFF)/0x100;
466 format
= format_native2esd(&conn
->sink_input
->sample_spec
);
470 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (int) (conn
->index
+1));
471 response
+= sizeof(int);
474 assert(conn
->client
);
475 strncpy(response
, conn
->client
->name
, ESD_NAME_MAX
);
476 response
+= ESD_NAME_MAX
;
479 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, rate
);
480 response
+= sizeof(int);
483 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, volume
);
484 response
+= sizeof(int);
487 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, volume
);
488 response
+= sizeof(int);
491 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, format
);
492 response
+= sizeof(int);
497 assert(t
== s
*(nsamples
+1)+k
);
498 memset(response
, 0, k
);
503 struct pa_scache_entry
*ce
;
505 index
= PA_IDXSET_INVALID
;
506 for (ce
= pa_idxset_first(c
->protocol
->core
->scache_idxset
, &index
); ce
; ce
= pa_idxset_next(c
->protocol
->core
->scache_idxset
, &index
)) {
510 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (int) (ce
->index
+1));
511 response
+= sizeof(int);
514 if (strncmp(ce
->name
, SCACHE_PREFIX
, sizeof(SCACHE_PREFIX
)-1) == 0)
515 strncpy(response
, ce
->name
+sizeof(SCACHE_PREFIX
)-1, ESD_NAME_MAX
);
517 snprintf(response
, ESD_NAME_MAX
, "native.%s", ce
->name
);
518 response
+= ESD_NAME_MAX
;
521 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, ce
->sample_spec
.rate
);
522 response
+= sizeof(int);
525 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (ce
->volume
*0xFF)/0x100);
526 response
+= sizeof(int);
529 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (ce
->volume
*0xFF)/0x100);
530 response
+= sizeof(int);
533 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, format_native2esd(&ce
->sample_spec
));
534 response
+= sizeof(int);
537 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (int) ce
->memchunk
.length
);
538 response
+= sizeof(int);
545 memset(response
, 0, s
);
550 static int esd_proto_stream_pan(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
552 uint32_t index
, volume
;
553 struct connection
*conn
;
554 assert(c
&& data
&& length
== sizeof(int)*3);
556 index
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
)-1;
557 volume
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
558 volume
= (volume
*0x100)/0xFF;
560 ok
= connection_write(c
, sizeof(int));
563 if ((conn
= pa_idxset_get_by_index(c
->protocol
->connections
, index
))) {
564 assert(conn
->sink_input
);
565 conn
->sink_input
->volume
= volume
;
573 static int esd_proto_sample_cache(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
574 struct pa_sample_spec ss
;
579 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
580 assert(c
&& data
&& length
== (ESD_NAME_MAX
+3*sizeof(int)));
582 format
= maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
583 rate
= maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
586 format_esd2native(format
, &ss
);
588 sc_length
= (size_t) maybe_swap_endian_32(c
->swap_byte_order
, (*((int*)data
+ 2)));
590 if (sc_length
>= MAX_CACHE_SAMPLE_SIZE
)
593 strcpy(name
, SCACHE_PREFIX
);
594 strncpy(name
+sizeof(SCACHE_PREFIX
)-1, data
+3*sizeof(int), ESD_NAME_MAX
);
595 name
[sizeof(name
)-1] = 0;
597 assert(!c
->scache_memchunk
.memblock
);
598 c
->scache_memchunk
.memblock
= pa_memblock_new(sc_length
);
599 c
->scache_memchunk
.index
= 0;
600 c
->scache_memchunk
.length
= sc_length
;
601 c
->scache_sample_spec
= ss
;
602 assert(!c
->scache_name
);
603 c
->scache_name
= strdup(name
);
604 assert(c
->scache_name
);
606 c
->state
= ESD_CACHING_SAMPLE
;
608 pa_scache_add_item(c
->protocol
->core
, c
->scache_name
, NULL
, NULL
, &index
);
610 ok
= connection_write(c
, sizeof(int));
618 static int esd_proto_sample_get_id(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
621 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
622 assert(c
&& data
&& length
== ESD_NAME_MAX
);
624 ok
= connection_write(c
, sizeof(int));
629 strcpy(name
, SCACHE_PREFIX
);
630 strncpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
631 name
[sizeof(name
)-1] = 0;
633 if ((index
= pa_scache_get_id_by_name(c
->protocol
->core
, name
)) != PA_IDXSET_INVALID
)
634 *ok
= (int) index
+1;
639 static int esd_proto_sample_free_or_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
643 assert(c
&& data
&& length
== sizeof(int));
645 index
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
)-1;
647 ok
= connection_write(c
, sizeof(int));
652 if ((name
= pa_scache_get_name_by_id(c
->protocol
->core
, index
))) {
653 if (request
== ESD_PROTO_SAMPLE_PLAY
) {
654 struct pa_sink
*sink
;
656 if ((sink
= get_output_sink(c
->protocol
)))
657 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, PA_VOLUME_NORM
) >= 0)
660 assert(request
== ESD_PROTO_SAMPLE_FREE
);
662 if (pa_scache_remove_item(c
->protocol
->core
, name
) >= 0)
670 /*** client callbacks ***/
672 static void client_kill_cb(struct pa_client
*c
) {
673 assert(c
&& c
->userdata
);
674 connection_free(c
->userdata
);
677 /*** pa_iochannel callbacks ***/
679 static int do_read(struct connection
*c
) {
682 if (c
->state
== ESD_NEXT_REQUEST
) {
684 assert(c
->read_data_length
< sizeof(c
->request
));
686 if ((r
= pa_iochannel_read(c
->io
, ((void*) &c
->request
) + c
->read_data_length
, sizeof(c
->request
) - c
->read_data_length
)) <= 0) {
687 fprintf(stderr
, "protocol-esound.c: read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
691 if ((c
->read_data_length
+= r
) >= sizeof(c
->request
)) {
692 struct proto_handler
*handler
;
694 if (c
->swap_byte_order
)
695 c
->request
= swap_endian_32(c
->request
);
697 if (c
->request
< ESD_PROTO_CONNECT
|| c
->request
> ESD_PROTO_MAX
) {
698 fprintf(stderr
, "protocol-esound.c: recieved invalid request.\n");
702 handler
= proto_map
+c
->request
;
704 if (!handler
->proc
) {
705 fprintf(stderr
, "protocol-sound.c: recieved unimplemented request.\n");
709 if (handler
->data_length
== 0) {
710 c
->read_data_length
= 0;
712 if (handler
->proc(c
, c
->request
, NULL
, 0) < 0)
716 if (c
->read_data_alloc
< handler
->data_length
)
717 c
->read_data
= realloc(c
->read_data
, c
->read_data_alloc
= handler
->data_length
);
718 assert(c
->read_data
);
720 c
->state
= ESD_NEEDS_REQDATA
;
721 c
->read_data_length
= 0;
725 } else if (c
->state
== ESD_NEEDS_REQDATA
) {
727 struct proto_handler
*handler
= proto_map
+c
->request
;
729 assert(handler
->proc
);
731 assert(c
->read_data
&& c
->read_data_length
< handler
->data_length
);
733 if ((r
= pa_iochannel_read(c
->io
, c
->read_data
+ c
->read_data_length
, handler
->data_length
- c
->read_data_length
)) <= 0) {
734 fprintf(stderr
, "protocol-esound.c: read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
738 if ((c
->read_data_length
+= r
) >= handler
->data_length
) {
739 size_t l
= c
->read_data_length
;
740 assert(handler
->proc
);
742 c
->state
= ESD_NEXT_REQUEST
;
743 c
->read_data_length
= 0;
745 if (handler
->proc(c
, c
->request
, c
->read_data
, l
) < 0)
748 } else if (c
->state
== ESD_CACHING_SAMPLE
) {
751 assert(c
->scache_memchunk
.memblock
&& c
->scache_name
&& c
->scache_memchunk
.index
< c
->scache_memchunk
.length
);
753 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) {
754 fprintf(stderr
, __FILE__
": read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
758 c
->scache_memchunk
.index
+= r
;
759 assert(c
->scache_memchunk
.index
<= c
->scache_memchunk
.length
);
761 if (c
->scache_memchunk
.index
== c
->scache_memchunk
.length
) {
765 c
->scache_memchunk
.index
= 0;
766 pa_scache_add_item(c
->protocol
->core
, c
->scache_name
, &c
->scache_sample_spec
, &c
->scache_memchunk
, &index
);
768 pa_memblock_unref(c
->scache_memchunk
.memblock
);
769 c
->scache_memchunk
.memblock
= NULL
;
770 c
->scache_memchunk
.index
= c
->scache_memchunk
.length
= 0;
772 free(c
->scache_name
);
773 c
->scache_name
= NULL
;
775 c
->state
= ESD_NEXT_REQUEST
;
777 ok
= connection_write(c
, sizeof(int));
782 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
783 struct pa_memchunk chunk
;
787 assert(c
->input_memblockq
);
789 if (!(l
= pa_memblockq_missing(c
->input_memblockq
)))
792 if (l
> c
->playback
.fragment_size
)
793 l
= c
->playback
.fragment_size
;
795 if (c
->playback
.current_memblock
)
796 if (c
->playback
.current_memblock
->length
- c
->playback
.memblock_index
< l
) {
797 pa_memblock_unref(c
->playback
.current_memblock
);
798 c
->playback
.current_memblock
= NULL
;
799 c
->playback
.memblock_index
= 0;
802 if (!c
->playback
.current_memblock
) {
803 c
->playback
.current_memblock
= pa_memblock_new(c
->playback
.fragment_size
*2);
804 assert(c
->playback
.current_memblock
&& c
->playback
.current_memblock
->length
>= l
);
805 c
->playback
.memblock_index
= 0;
808 if ((r
= pa_iochannel_read(c
->io
, c
->playback
.current_memblock
->data
+c
->playback
.memblock_index
, l
)) <= 0) {
809 fprintf(stderr
, __FILE__
": read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
813 chunk
.memblock
= c
->playback
.current_memblock
;
814 chunk
.index
= c
->playback
.memblock_index
;
816 assert(chunk
.memblock
);
818 c
->playback
.memblock_index
+= r
;
820 assert(c
->input_memblockq
);
821 pa_memblockq_push_align(c
->input_memblockq
, &chunk
, 0);
822 assert(c
->sink_input
);
823 pa_sink_notify(c
->sink_input
->sink
);
829 static int do_write(struct connection
*c
) {
832 if (c
->write_data_length
) {
835 assert(c
->write_data_index
< c
->write_data_length
);
836 if ((r
= pa_iochannel_write(c
->io
, c
->write_data
+c
->write_data_index
, c
->write_data_length
-c
->write_data_index
)) < 0) {
837 fprintf(stderr
, __FILE__
": write() failed: %s\n", strerror(errno
));
841 if ((c
->write_data_index
+=r
) >= c
->write_data_length
)
842 c
->write_data_length
= c
->write_data_index
= 0;
844 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->source_output
) {
845 struct pa_memchunk chunk
;
848 assert(c
->output_memblockq
);
849 if (pa_memblockq_peek(c
->output_memblockq
, &chunk
) < 0)
852 assert(chunk
.memblock
&& chunk
.length
);
854 if ((r
= pa_iochannel_write(c
->io
, chunk
.memblock
->data
+chunk
.index
, chunk
.length
)) < 0) {
855 pa_memblock_unref(chunk
.memblock
);
856 fprintf(stderr
, __FILE__
": write(): %s\n", strerror(errno
));
860 pa_memblockq_drop(c
->output_memblockq
, r
);
861 pa_memblock_unref(chunk
.memblock
);
867 static void do_work(struct connection
*c
) {
870 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->enable_fixed
);
871 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 0);
873 if (pa_iochannel_is_hungup(c
->io
))
876 if (pa_iochannel_is_writable(c
->io
))
880 if (pa_iochannel_is_readable(c
->io
))
890 static void io_callback(struct pa_iochannel
*io
, void *userdata
) {
891 struct connection
*c
= userdata
;
892 assert(io
&& c
&& c
->io
== io
);
897 /*** fixed callback ***/
899 static void fixed_callback(struct pa_mainloop_api
*a
, void *id
, void *userdata
) {
900 struct connection
*c
= userdata
;
901 assert(a
&& c
&& c
->fixed_source
== id
);
906 /*** sink_input callbacks ***/
908 static int sink_input_peek_cb(struct pa_sink_input
*i
, struct pa_memchunk
*chunk
) {
910 assert(i
&& i
->userdata
&& chunk
);
913 if (pa_memblockq_peek(c
->input_memblockq
, chunk
) < 0)
919 static void sink_input_drop_cb(struct pa_sink_input
*i
, size_t length
) {
920 struct connection
*c
= i
->userdata
;
921 assert(i
&& c
&& length
);
923 pa_memblockq_drop(c
->input_memblockq
, length
);
926 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->enable_fixed
);
927 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 1);
930 static void sink_input_kill_cb(struct pa_sink_input
*i
) {
931 assert(i
&& i
->userdata
);
932 connection_free((struct connection
*) i
->userdata
);
936 static uint32_t sink_input_get_latency_cb(struct pa_sink_input
*i
) {
937 struct connection
*c
= i
->userdata
;
939 return pa_bytes_to_usec(pa_memblockq_get_length(c
->input_memblockq
), &c
->sink_input
->sample_spec
);
942 /*** source_output callbacks ***/
944 static void source_output_push_cb(struct pa_source_output
*o
, const struct pa_memchunk
*chunk
) {
945 struct connection
*c
= o
->userdata
;
946 assert(o
&& c
&& chunk
);
948 pa_memblockq_push(c
->output_memblockq
, chunk
, 0);
951 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->enable_fixed
);
952 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 1);
955 static void source_output_kill_cb(struct pa_source_output
*o
) {
956 assert(o
&& o
->userdata
);
957 connection_free((struct connection
*) o
->userdata
);
960 /*** socket server callback ***/
962 static void on_connection(struct pa_socket_server
*s
, struct pa_iochannel
*io
, void *userdata
) {
963 struct connection
*c
;
965 assert(s
&& io
&& userdata
);
967 c
= malloc(sizeof(struct connection
));
969 c
->protocol
= userdata
;
971 pa_iochannel_set_callback(c
->io
, io_callback
, c
);
973 pa_iochannel_socket_peer_to_string(io
, cname
, sizeof(cname
));
974 assert(c
->protocol
->core
);
975 c
->client
= pa_client_new(c
->protocol
->core
, "ESOUND", cname
);
977 c
->client
->owner
= c
->protocol
->module
;
978 c
->client
->kill
= client_kill_cb
;
979 c
->client
->userdata
= c
;
981 c
->authorized
= c
->protocol
->public;
982 c
->swap_byte_order
= 0;
984 c
->read_data_length
= 0;
985 c
->read_data
= malloc(c
->read_data_alloc
= proto_map
[ESD_PROTO_CONNECT
].data_length
);
986 assert(c
->read_data
);
988 c
->write_data_length
= c
->write_data_index
= c
->write_data_alloc
= 0;
989 c
->write_data
= NULL
;
991 c
->state
= ESD_NEEDS_REQDATA
;
992 c
->request
= ESD_PROTO_CONNECT
;
994 c
->sink_input
= NULL
;
995 c
->input_memblockq
= NULL
;
997 c
->source_output
= NULL
;
998 c
->output_memblockq
= NULL
;
1000 c
->playback
.current_memblock
= NULL
;
1001 c
->playback
.memblock_index
= 0;
1002 c
->playback
.fragment_size
= 0;
1004 c
->scache_memchunk
.length
= c
->scache_memchunk
.index
= 0;
1005 c
->scache_memchunk
.memblock
= NULL
;
1006 c
->scache_name
= NULL
;
1008 c
->fixed_source
= c
->protocol
->core
->mainloop
->source_fixed(c
->protocol
->core
->mainloop
, fixed_callback
, c
);
1009 assert(c
->fixed_source
);
1010 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 0);
1012 pa_idxset_put(c
->protocol
->connections
, c
, &c
->index
);
1015 /*** entry points ***/
1017 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
) {
1018 uint32_t source_index
, sink_index
;
1019 struct pa_protocol_esound
*p
;
1020 assert(core
&& server
&& ma
);
1022 if (pa_modargs_get_source_index(ma
, core
, &source_index
) < 0) {
1023 fprintf(stderr
, __FILE__
": source does not exist.\n");
1027 if (pa_modargs_get_sink_index(ma
, core
, &sink_index
) < 0) {
1028 fprintf(stderr
, __FILE__
": sink does not exist.\n");
1031 p
= malloc(sizeof(struct pa_protocol_esound
));
1034 if (pa_authkey_load_auto(pa_modargs_get_value(ma
, "cookie", DEFAULT_COOKIE_FILE
), p
->esd_key
, sizeof(p
->esd_key
)) < 0) {
1042 pa_socket_server_set_callback(p
->server
, on_connection
, p
);
1044 p
->connections
= pa_idxset_new(NULL
, NULL
);
1045 assert(p
->connections
);
1046 p
->sink_index
= sink_index
;
1047 p
->source_index
= source_index
;
1053 void pa_protocol_esound_free(struct pa_protocol_esound
*p
) {
1054 struct connection
*c
;
1057 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
1060 pa_idxset_free(p
->connections
, NULL
, NULL
);
1061 pa_socket_server_free(p
->server
);