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
)))
305 strncpy(name
, data
+ sizeof(int)*2, sizeof(name
));
306 name
[sizeof(name
)-1] = 0;
308 pa_client_rename(c
->client
, name
);
310 assert(!c
->input_memblockq
);
312 l
= (size_t) (pa_bytes_per_second(&ss
)*PLAYBACK_BUFFER_SECONDS
);
313 c
->input_memblockq
= pa_memblockq_new(l
, 0, pa_sample_size(&ss
), l
/2, l
/PLAYBACK_BUFFER_FRAGMENTS
);
314 assert(c
->input_memblockq
);
315 pa_iochannel_socket_set_rcvbuf(c
->io
, l
/PLAYBACK_BUFFER_FRAGMENTS
*2);
316 c
->playback
.fragment_size
= l
/10;
318 assert(!c
->sink_input
);
319 c
->sink_input
= pa_sink_input_new(sink
, name
, &ss
);
320 assert(c
->sink_input
);
322 c
->sink_input
->owner
= c
->protocol
->module
;
323 c
->sink_input
->client
= c
->client
;
324 c
->sink_input
->peek
= sink_input_peek_cb
;
325 c
->sink_input
->drop
= sink_input_drop_cb
;
326 c
->sink_input
->kill
= sink_input_kill_cb
;
327 c
->sink_input
->get_latency
= sink_input_get_latency_cb
;
328 c
->sink_input
->userdata
= c
;
330 c
->state
= ESD_STREAMING_DATA
;
332 c
->protocol
->n_player
++;
337 static int esd_proto_stream_record(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
338 char name
[ESD_NAME_MAX
];
340 struct pa_source
*source
;
341 struct pa_sample_spec ss
;
343 assert(c
&& length
== (sizeof(int)*2+ESD_NAME_MAX
));
345 format
= maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
346 rate
= maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
349 format_esd2native(format
, &ss
);
351 if (!pa_sample_spec_valid(&ss
))
354 if (request
== ESD_PROTO_STREAM_MON
) {
355 struct pa_sink
* sink
;
357 if (!(sink
= get_output_sink(c
->protocol
)))
360 if (!(source
= sink
->monitor_source
))
363 assert(request
== ESD_PROTO_STREAM_REC
);
365 if (!(source
= get_input_source(c
->protocol
)))
369 strncpy(name
, data
+ sizeof(int)*2, sizeof(name
));
370 name
[sizeof(name
)-1] = 0;
372 pa_client_rename(c
->client
, name
);
374 assert(!c
->output_memblockq
);
376 l
= (size_t) (pa_bytes_per_second(&ss
)*RECORD_BUFFER_SECONDS
);
377 c
->output_memblockq
= pa_memblockq_new(l
, 0, pa_sample_size(&ss
), 0, 0);
378 assert(c
->output_memblockq
);
379 pa_iochannel_socket_set_sndbuf(c
->io
, l
/RECORD_BUFFER_FRAGMENTS
*2);
381 assert(!c
->source_output
);
382 c
->source_output
= pa_source_output_new(source
, name
, &ss
);
383 assert(c
->source_output
);
385 c
->source_output
->owner
= c
->protocol
->module
;
386 c
->source_output
->client
= c
->client
;
387 c
->source_output
->push
= source_output_push_cb
;
388 c
->source_output
->kill
= source_output_kill_cb
;
389 c
->source_output
->userdata
= c
;
391 c
->state
= ESD_STREAMING_DATA
;
393 c
->protocol
->n_player
++;
398 static int esd_proto_get_latency(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
399 struct pa_sink
*sink
;
401 assert(c
&& !data
&& length
== 0);
403 if (!(sink
= get_output_sink(c
->protocol
)))
406 float usec
= pa_sink_get_latency(sink
);
407 usec
+= PLAYBACK_BUFFER_SECONDS
*1000000; /* A better estimation would be a good idea! */
408 latency
= (int) ((usec
*44100)/1000000);
411 lag
= connection_write(c
, sizeof(int));
413 *lag
= c
->swap_byte_order
? swap_endian_32(latency
) : latency
;
417 static int esd_proto_server_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
418 int rate
= 44100, format
= ESD_STEREO
|ESD_BITS16
;
420 struct pa_sink
*sink
;
421 assert(c
&& data
&& length
== sizeof(int));
423 if ((sink
= get_output_sink(c
->protocol
))) {
424 rate
= sink
->sample_spec
.rate
;
425 format
= format_native2esd(&sink
->sample_spec
);
428 response
= connection_write(c
, sizeof(int)*3);
431 *(response
++) = maybe_swap_endian_32(c
->swap_byte_order
, rate
);
432 *(response
++) = maybe_swap_endian_32(c
->swap_byte_order
, format
);
436 static int esd_proto_all_info(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
439 struct connection
*conn
;
440 size_t index
= PA_IDXSET_INVALID
;
441 assert(c
&& data
&& length
== sizeof(int));
443 if (esd_proto_server_info(c
, request
, data
, length
) < 0)
446 k
= sizeof(int)*5+ESD_NAME_MAX
;
447 s
= sizeof(int)*6+ESD_NAME_MAX
;
448 response
= connection_write(c
, (t
= s
+k
*(c
->protocol
->n_player
+1)));
451 for (conn
= pa_idxset_first(c
->protocol
->connections
, &index
); conn
; conn
= pa_idxset_next(c
->protocol
->connections
, &index
)) {
452 int format
= ESD_BITS16
| ESD_STEREO
, rate
= 44100, volume
= 0xFF;
454 if (conn
->state
!= ESD_STREAMING_DATA
)
459 if (conn
->sink_input
) {
460 rate
= conn
->sink_input
->sample_spec
.rate
;
461 volume
= (conn
->sink_input
->volume
*0xFF)/0x100;
462 format
= format_native2esd(&conn
->sink_input
->sample_spec
);
466 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, (int) conn
->index
);
467 response
+= sizeof(int);
470 assert(conn
->client
);
471 strncpy(response
, conn
->client
->name
, ESD_NAME_MAX
);
472 response
+= ESD_NAME_MAX
;
475 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, rate
);
476 response
+= sizeof(int);
479 *((int*) response
) = maybe_swap_endian_32(c
->swap_byte_order
, volume
);
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
, format
);
488 response
+= sizeof(int);
494 memset(response
, 0, t
);
498 static int esd_proto_stream_pan(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
500 uint32_t index
, volume
;
501 struct connection
*conn
;
502 assert(c
&& data
&& length
== sizeof(int)*3);
504 index
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
505 volume
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
506 volume
= (volume
*0x100)/0xFF;
508 ok
= connection_write(c
, sizeof(int));
511 if ((conn
= pa_idxset_get_by_index(c
->protocol
->connections
, index
))) {
512 assert(conn
->sink_input
);
513 conn
->sink_input
->volume
= volume
;
521 static int esd_proto_sample_cache(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
522 struct pa_sample_spec ss
;
527 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
528 assert(c
&& data
&& length
== (ESD_NAME_MAX
+3*sizeof(int)));
530 format
= maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
);
531 rate
= maybe_swap_endian_32(c
->swap_byte_order
, *((int*)data
+ 1));
534 format_esd2native(format
, &ss
);
536 sc_length
= (size_t) maybe_swap_endian_32(c
->swap_byte_order
, (*((int*)data
+ 2)));
538 if (sc_length
>= MAX_CACHE_SAMPLE_SIZE
)
541 strcpy(name
, SCACHE_PREFIX
);
542 strncpy(name
+sizeof(SCACHE_PREFIX
)-1, data
+3*sizeof(int), ESD_NAME_MAX
);
543 name
[sizeof(name
)-1] = 0;
545 assert(!c
->scache_memchunk
.memblock
);
546 c
->scache_memchunk
.memblock
= pa_memblock_new(sc_length
);
547 c
->scache_memchunk
.index
= 0;
548 c
->scache_memchunk
.length
= sc_length
;
549 c
->scache_sample_spec
= ss
;
550 assert(!c
->scache_name
);
551 c
->scache_name
= strdup(name
);
552 assert(c
->scache_name
);
554 c
->state
= ESD_CACHING_SAMPLE
;
556 pa_scache_add_item(c
->protocol
->core
, c
->scache_name
, NULL
, NULL
, &index
);
558 ok
= connection_write(c
, sizeof(int));
566 static int esd_proto_sample_get_id(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
569 char name
[ESD_NAME_MAX
+sizeof(SCACHE_PREFIX
)-1];
570 assert(c
&& data
&& length
== ESD_NAME_MAX
);
572 ok
= connection_write(c
, sizeof(int));
577 strcpy(name
, SCACHE_PREFIX
);
578 strncpy(name
+sizeof(SCACHE_PREFIX
)-1, data
, ESD_NAME_MAX
);
579 name
[sizeof(name
)-1] = 0;
581 if ((index
= pa_scache_get_id_by_name(c
->protocol
->core
, name
)) != PA_IDXSET_INVALID
)
582 *ok
= (int) index
+1;
587 static int esd_proto_sample_free_or_play(struct connection
*c
, esd_proto_t request
, const void *data
, size_t length
) {
591 assert(c
&& data
&& length
== sizeof(int));
593 index
= (uint32_t) maybe_swap_endian_32(c
->swap_byte_order
, *(int*)data
)-1;
595 ok
= connection_write(c
, sizeof(int));
600 if ((name
= pa_scache_get_name_by_id(c
->protocol
->core
, index
))) {
601 if (request
== ESD_PROTO_SAMPLE_PLAY
) {
602 struct pa_sink
*sink
;
604 if ((sink
= get_output_sink(c
->protocol
)))
605 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, PA_VOLUME_NORM
) >= 0)
608 assert(request
== ESD_PROTO_SAMPLE_FREE
);
610 if (pa_scache_remove_item(c
->protocol
->core
, name
) >= 0)
618 /*** client callbacks ***/
620 static void client_kill_cb(struct pa_client
*c
) {
621 assert(c
&& c
->userdata
);
622 connection_free(c
->userdata
);
625 /*** pa_iochannel callbacks ***/
627 static int do_read(struct connection
*c
) {
630 if (c
->state
== ESD_NEXT_REQUEST
) {
632 assert(c
->read_data_length
< sizeof(c
->request
));
634 if ((r
= pa_iochannel_read(c
->io
, ((void*) &c
->request
) + c
->read_data_length
, sizeof(c
->request
) - c
->read_data_length
)) <= 0) {
635 fprintf(stderr
, "protocol-esound.c: read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
639 if ((c
->read_data_length
+= r
) >= sizeof(c
->request
)) {
640 struct proto_handler
*handler
;
642 if (c
->swap_byte_order
)
643 c
->request
= swap_endian_32(c
->request
);
645 if (c
->request
< ESD_PROTO_CONNECT
|| c
->request
> ESD_PROTO_MAX
) {
646 fprintf(stderr
, "protocol-esound.c: recieved invalid request.\n");
650 handler
= proto_map
+c
->request
;
652 if (!handler
->proc
) {
653 fprintf(stderr
, "protocol-sound.c: recieved unimplemented request.\n");
657 if (handler
->data_length
== 0) {
658 c
->read_data_length
= 0;
660 if (handler
->proc(c
, c
->request
, NULL
, 0) < 0)
664 if (c
->read_data_alloc
< handler
->data_length
)
665 c
->read_data
= realloc(c
->read_data
, c
->read_data_alloc
= handler
->data_length
);
666 assert(c
->read_data
);
668 c
->state
= ESD_NEEDS_REQDATA
;
669 c
->read_data_length
= 0;
673 } else if (c
->state
== ESD_NEEDS_REQDATA
) {
675 struct proto_handler
*handler
= proto_map
+c
->request
;
677 assert(handler
->proc
);
679 assert(c
->read_data
&& c
->read_data_length
< handler
->data_length
);
681 if ((r
= pa_iochannel_read(c
->io
, c
->read_data
+ c
->read_data_length
, handler
->data_length
- c
->read_data_length
)) <= 0) {
682 fprintf(stderr
, "protocol-esound.c: read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
686 if ((c
->read_data_length
+= r
) >= handler
->data_length
) {
687 size_t l
= c
->read_data_length
;
688 assert(handler
->proc
);
690 c
->state
= ESD_NEXT_REQUEST
;
691 c
->read_data_length
= 0;
693 if (handler
->proc(c
, c
->request
, c
->read_data
, l
) < 0)
696 } else if (c
->state
== ESD_CACHING_SAMPLE
) {
699 assert(c
->scache_memchunk
.memblock
&& c
->scache_name
&& c
->scache_memchunk
.index
< c
->scache_memchunk
.length
);
701 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) {
702 fprintf(stderr
, __FILE__
": read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
706 c
->scache_memchunk
.index
+= r
;
707 assert(c
->scache_memchunk
.index
<= c
->scache_memchunk
.length
);
709 if (c
->scache_memchunk
.index
== c
->scache_memchunk
.length
) {
713 c
->scache_memchunk
.index
= 0;
714 pa_scache_add_item(c
->protocol
->core
, c
->scache_name
, &c
->scache_sample_spec
, &c
->scache_memchunk
, &index
);
716 pa_memblock_unref(c
->scache_memchunk
.memblock
);
717 c
->scache_memchunk
.memblock
= NULL
;
718 c
->scache_memchunk
.index
= c
->scache_memchunk
.length
= 0;
720 free(c
->scache_name
);
721 c
->scache_name
= NULL
;
723 c
->state
= ESD_NEXT_REQUEST
;
725 ok
= connection_write(c
, sizeof(int));
730 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->sink_input
) {
731 struct pa_memchunk chunk
;
735 assert(c
->input_memblockq
);
737 if (!(l
= pa_memblockq_missing(c
->input_memblockq
)))
740 if (l
> c
->playback
.fragment_size
)
741 l
= c
->playback
.fragment_size
;
743 if (c
->playback
.current_memblock
)
744 if (c
->playback
.current_memblock
->length
- c
->playback
.memblock_index
< l
) {
745 pa_memblock_unref(c
->playback
.current_memblock
);
746 c
->playback
.current_memblock
= NULL
;
747 c
->playback
.memblock_index
= 0;
750 if (!c
->playback
.current_memblock
) {
751 c
->playback
.current_memblock
= pa_memblock_new(c
->playback
.fragment_size
*2);
752 assert(c
->playback
.current_memblock
&& c
->playback
.current_memblock
->length
>= l
);
753 c
->playback
.memblock_index
= 0;
756 if ((r
= pa_iochannel_read(c
->io
, c
->playback
.current_memblock
->data
+c
->playback
.memblock_index
, l
)) <= 0) {
757 fprintf(stderr
, __FILE__
": read() failed: %s\n", r
== 0 ? "EOF" : strerror(errno
));
761 chunk
.memblock
= c
->playback
.current_memblock
;
762 chunk
.index
= c
->playback
.memblock_index
;
764 assert(chunk
.memblock
);
766 c
->playback
.memblock_index
+= r
;
768 assert(c
->input_memblockq
);
769 pa_memblockq_push_align(c
->input_memblockq
, &chunk
, 0);
770 assert(c
->sink_input
);
771 pa_sink_notify(c
->sink_input
->sink
);
777 static int do_write(struct connection
*c
) {
780 if (c
->write_data_length
) {
783 assert(c
->write_data_index
< c
->write_data_length
);
784 if ((r
= pa_iochannel_write(c
->io
, c
->write_data
+c
->write_data_index
, c
->write_data_length
-c
->write_data_index
)) < 0) {
785 fprintf(stderr
, __FILE__
": write() failed: %s\n", strerror(errno
));
789 if ((c
->write_data_index
+=r
) >= c
->write_data_length
)
790 c
->write_data_length
= c
->write_data_index
= 0;
792 } else if (c
->state
== ESD_STREAMING_DATA
&& c
->source_output
) {
793 struct pa_memchunk chunk
;
796 assert(c
->output_memblockq
);
797 if (pa_memblockq_peek(c
->output_memblockq
, &chunk
) < 0)
800 assert(chunk
.memblock
&& chunk
.length
);
802 if ((r
= pa_iochannel_write(c
->io
, chunk
.memblock
->data
+chunk
.index
, chunk
.length
)) < 0) {
803 pa_memblock_unref(chunk
.memblock
);
804 fprintf(stderr
, __FILE__
": write(): %s\n", strerror(errno
));
808 pa_memblockq_drop(c
->output_memblockq
, r
);
809 pa_memblock_unref(chunk
.memblock
);
815 static void do_work(struct connection
*c
) {
818 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->enable_fixed
);
819 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 0);
821 if (pa_iochannel_is_hungup(c
->io
))
824 if (pa_iochannel_is_writable(c
->io
))
828 if (pa_iochannel_is_readable(c
->io
))
838 static void io_callback(struct pa_iochannel
*io
, void *userdata
) {
839 struct connection
*c
= userdata
;
840 assert(io
&& c
&& c
->io
== io
);
845 /*** fixed callback ***/
847 static void fixed_callback(struct pa_mainloop_api
*a
, void *id
, void *userdata
) {
848 struct connection
*c
= userdata
;
849 assert(a
&& c
&& c
->fixed_source
== id
);
854 /*** sink_input callbacks ***/
856 static int sink_input_peek_cb(struct pa_sink_input
*i
, struct pa_memchunk
*chunk
) {
858 assert(i
&& i
->userdata
&& chunk
);
861 if (pa_memblockq_peek(c
->input_memblockq
, chunk
) < 0)
867 static void sink_input_drop_cb(struct pa_sink_input
*i
, size_t length
) {
868 struct connection
*c
= i
->userdata
;
869 assert(i
&& c
&& length
);
871 pa_memblockq_drop(c
->input_memblockq
, length
);
874 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->enable_fixed
);
875 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 1);
878 static void sink_input_kill_cb(struct pa_sink_input
*i
) {
879 assert(i
&& i
->userdata
);
880 connection_free((struct connection
*) i
->userdata
);
884 static uint32_t sink_input_get_latency_cb(struct pa_sink_input
*i
) {
885 struct connection
*c
= i
->userdata
;
887 return pa_samples_usec(pa_memblockq_get_length(c
->input_memblockq
), &c
->sink_input
->sample_spec
);
890 /*** source_output callbacks ***/
892 static void source_output_push_cb(struct pa_source_output
*o
, const struct pa_memchunk
*chunk
) {
893 struct connection
*c
= o
->userdata
;
894 assert(o
&& c
&& chunk
);
896 pa_memblockq_push(c
->output_memblockq
, chunk
, 0);
899 assert(c
->protocol
&& c
->protocol
->core
&& c
->protocol
->core
->mainloop
&& c
->protocol
->core
->mainloop
->enable_fixed
);
900 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 1);
903 static void source_output_kill_cb(struct pa_source_output
*o
) {
904 assert(o
&& o
->userdata
);
905 connection_free((struct connection
*) o
->userdata
);
908 /*** socket server callback ***/
910 static void on_connection(struct pa_socket_server
*s
, struct pa_iochannel
*io
, void *userdata
) {
911 struct connection
*c
;
913 assert(s
&& io
&& userdata
);
915 c
= malloc(sizeof(struct connection
));
917 c
->protocol
= userdata
;
919 pa_iochannel_set_callback(c
->io
, io_callback
, c
);
921 pa_iochannel_socket_peer_to_string(io
, cname
, sizeof(cname
));
922 assert(c
->protocol
->core
);
923 c
->client
= pa_client_new(c
->protocol
->core
, "ESOUND", cname
);
925 c
->client
->owner
= c
->protocol
->module
;
926 c
->client
->kill
= client_kill_cb
;
927 c
->client
->userdata
= c
;
929 c
->authorized
= c
->protocol
->public;
930 c
->swap_byte_order
= 0;
932 c
->read_data_length
= 0;
933 c
->read_data
= malloc(c
->read_data_alloc
= proto_map
[ESD_PROTO_CONNECT
].data_length
);
934 assert(c
->read_data
);
936 c
->write_data_length
= c
->write_data_index
= c
->write_data_alloc
= 0;
937 c
->write_data
= NULL
;
939 c
->state
= ESD_NEEDS_REQDATA
;
940 c
->request
= ESD_PROTO_CONNECT
;
942 c
->sink_input
= NULL
;
943 c
->input_memblockq
= NULL
;
945 c
->source_output
= NULL
;
946 c
->output_memblockq
= NULL
;
948 c
->playback
.current_memblock
= NULL
;
949 c
->playback
.memblock_index
= 0;
950 c
->playback
.fragment_size
= 0;
952 c
->scache_memchunk
.length
= c
->scache_memchunk
.index
= 0;
953 c
->scache_memchunk
.memblock
= NULL
;
954 c
->scache_name
= NULL
;
956 c
->fixed_source
= c
->protocol
->core
->mainloop
->source_fixed(c
->protocol
->core
->mainloop
, fixed_callback
, c
);
957 assert(c
->fixed_source
);
958 c
->protocol
->core
->mainloop
->enable_fixed(c
->protocol
->core
->mainloop
, c
->fixed_source
, 0);
960 pa_idxset_put(c
->protocol
->connections
, c
, &c
->index
);
963 /*** entry points ***/
965 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
) {
966 uint32_t source_index
, sink_index
;
967 struct pa_protocol_esound
*p
;
968 assert(core
&& server
&& ma
);
970 if (pa_modargs_get_source_index(ma
, core
, &source_index
) < 0) {
971 fprintf(stderr
, __FILE__
": source does not exist.\n");
975 if (pa_modargs_get_sink_index(ma
, core
, &sink_index
) < 0) {
976 fprintf(stderr
, __FILE__
": sink does not exist.\n");
979 p
= malloc(sizeof(struct pa_protocol_esound
));
982 if (pa_authkey_load_auto(pa_modargs_get_value(ma
, "cookie", DEFAULT_COOKIE_FILE
), p
->esd_key
, sizeof(p
->esd_key
)) < 0) {
990 pa_socket_server_set_callback(p
->server
, on_connection
, p
);
992 p
->connections
= pa_idxset_new(NULL
, NULL
);
993 assert(p
->connections
);
994 p
->sink_index
= sink_index
;
995 p
->source_index
= source_index
;
1001 void pa_protocol_esound_free(struct pa_protocol_esound
*p
) {
1002 struct connection
*c
;
1005 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
1008 pa_idxset_free(p
->connections
, NULL
, NULL
);
1009 pa_socket_server_free(p
->server
);