1d61e01b1df13759e102967b2ae84068bfd44349
[profile/ivi/pulseaudio.git] / src / modules / module-esound-sink.c
1 /* $Id$ */
2
3 /***
4   This file is part of polypaudio.
5  
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.
10  
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.
15  
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
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <sys/stat.h>
28 #include <stdio.h>
29 #include <assert.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <limits.h>
35
36 #include <polyp/xmalloc.h>
37
38 #include <polypcore/iochannel.h>
39 #include <polypcore/sink.h>
40 #include <polypcore/module.h>
41 #include <polypcore/util.h>
42 #include <polypcore/modargs.h>
43 #include <polypcore/log.h>
44 #include <polypcore/socket-client.h>
45 #include <polypcore/esound.h>
46 #include <polypcore/authkey.h>
47
48 #include "module-esound-sink-symdef.h"
49
50 PA_MODULE_AUTHOR("Lennart Poettering")
51 PA_MODULE_DESCRIPTION("ESOUND Sink")
52 PA_MODULE_VERSION(PACKAGE_VERSION)
53 PA_MODULE_USAGE("sink_name=<name for the sink> server=<address> cookie=<filename>  format=<sample format> channels=<number of channels> rate=<sample rate>")
54
55 #define DEFAULT_SINK_NAME "esound_output"
56
57 struct userdata {
58     pa_core *core;
59
60     pa_sink *sink;
61     pa_iochannel *io;
62     pa_socket_client *client;
63
64     pa_defer_event *defer_event;
65
66     pa_memchunk memchunk;
67     pa_module *module;
68
69     void *write_data;
70     size_t write_length, write_index;
71     
72     void *read_data;
73     size_t read_length, read_index;
74
75     enum { STATE_AUTH, STATE_LATENCY, STATE_RUNNING, STATE_DEAD } state;
76
77     pa_usec_t latency;
78
79     esd_format_t format;
80     int32_t rate;
81 };
82
83 static const char* const valid_modargs[] = {
84     "server",
85     "cookie",
86     "rate",
87     "format",
88     "channels",
89     "sink_name",
90     NULL
91 };
92
93 static void cancel(struct userdata *u) {
94     assert(u);
95
96     u->state = STATE_DEAD;
97
98     if (u->io) {
99         pa_iochannel_free(u->io);
100         u->io = NULL;
101     }
102
103     if (u->defer_event) {
104         u->core->mainloop->defer_free(u->defer_event);
105         u->defer_event = NULL;
106     }
107
108     if (u->sink) {
109         pa_sink_disconnect(u->sink);
110         pa_sink_unref(u->sink);
111         u->sink = NULL;
112     }
113
114     if (u->module) {
115         pa_module_unload_request(u->module);
116         u->module = NULL;
117     }
118 }
119
120 static int do_write(struct userdata *u) {
121     ssize_t r;
122     assert(u);
123
124     if (!pa_iochannel_is_writable(u->io))
125         return 0;
126
127     if (u->write_data) {
128         assert(u->write_index < u->write_length);
129
130         if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) {
131             pa_log(__FILE__": write() failed: %s", strerror(errno));
132             return -1;
133         }
134
135         u->write_index += r;
136         assert(u->write_index <= u->write_length);
137         
138         if (u->write_index == u->write_length) {
139             free(u->write_data);
140             u->write_data = NULL;
141             u->write_index = u->write_length = 0;
142         }
143     } else if (u->state == STATE_RUNNING) {
144         pa_module_set_used(u->module, pa_idxset_size(u->sink->inputs) + pa_idxset_size(u->sink->monitor_source->outputs));
145         
146         if (!u->memchunk.length)
147             if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0)
148                 return 0;
149
150         assert(u->memchunk.memblock && u->memchunk.length);
151         
152         if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
153             pa_log(__FILE__": write() failed: %s", strerror(errno));
154             return -1;
155         }
156
157         u->memchunk.index += r;
158         u->memchunk.length -= r;
159         
160         if (u->memchunk.length <= 0) {
161             pa_memblock_unref(u->memchunk.memblock);
162             u->memchunk.memblock = NULL;
163         }
164     }
165     
166     return 0;
167 }
168
169 static int handle_response(struct userdata *u) {
170     assert(u);
171
172     switch (u->state) {
173         case STATE_AUTH:
174             assert(u->read_length == sizeof(int32_t));
175
176             /* Process auth data */
177             if (!*(int32_t*) u->read_data) {
178                 pa_log(__FILE__": Authentication failed: %s", strerror(errno));
179                 return -1;
180             }
181
182             /* Request latency data */
183             assert(!u->write_data);
184             *(int32_t*) (u->write_data = pa_xmalloc(u->write_length = sizeof(int32_t))) = ESD_PROTO_LATENCY;
185
186             u->write_index = 0;
187             u->state = STATE_LATENCY;
188
189             /* Space for next response */
190             assert(u->read_length >= sizeof(int32_t));
191             u->read_index = 0;
192             u->read_length = sizeof(int32_t);
193             
194             break;
195
196         case STATE_LATENCY: {
197             int32_t *p;
198             assert(u->read_length == sizeof(int32_t));
199
200             /* Process latency info */
201             u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100);
202             if (u->latency > 10000000) {
203                 pa_log(__FILE__": WARNING! Invalid latency information received from server");
204                 u->latency = 0;
205             }
206
207             /* Create stream */
208             assert(!u->write_data);
209             p = u->write_data = pa_xmalloc0(u->write_length = sizeof(int32_t)*3+ESD_NAME_MAX);
210             *(p++) = ESD_PROTO_STREAM_PLAY;
211             *(p++) = u->format;
212             *(p++) = u->rate;
213             pa_strlcpy((char*) p, "Polypaudio Tunnel", ESD_NAME_MAX);
214
215             u->write_index = 0;
216             u->state = STATE_RUNNING;
217
218             /* Don't read any further */
219             pa_xfree(u->read_data);
220             u->read_data = NULL;
221             u->read_index = u->read_length = 0;
222             
223             break;
224         }
225             
226         default:
227             abort();
228     }
229
230     return 0;
231 }
232
233 static int do_read(struct userdata *u) {
234     assert(u);
235     
236     if (!pa_iochannel_is_readable(u->io))
237         return 0;
238     
239     if (u->state == STATE_AUTH || u->state == STATE_LATENCY) {
240         ssize_t r;
241         
242         if (!u->read_data)
243             return 0;
244         
245         assert(u->read_index < u->read_length);
246         
247         if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) {
248             pa_log(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF");
249             cancel(u);
250             return -1;
251         }
252
253         u->read_index += r;
254         assert(u->read_index <= u->read_length);
255
256         if (u->read_index == u->read_length)
257             return handle_response(u);
258     }
259
260     return 0;
261 }
262
263 static void do_work(struct userdata *u) {
264     assert(u);
265
266     u->core->mainloop->defer_enable(u->defer_event, 0);
267     
268     if (do_read(u) < 0 || do_write(u) < 0)
269         cancel(u);
270 }
271
272 static void notify_cb(pa_sink*s) {
273     struct userdata *u = s->userdata;
274     assert(s && u);
275
276     if (pa_iochannel_is_writable(u->io))
277         u->core->mainloop->defer_enable(u->defer_event, 1);
278 }
279
280 static pa_usec_t get_latency_cb(pa_sink *s) {
281     struct userdata *u = s->userdata;
282     assert(s && u);
283
284     return
285         u->latency +
286         (u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0);
287 }
288
289 static void defer_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event*e, void *userdata) {
290     struct userdata *u = userdata;
291     assert(u);
292     do_work(u);
293 }
294
295 static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
296     struct userdata *u = userdata;
297     assert(u);
298     do_work(u);
299 }
300
301 static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, void *userdata) {
302     struct userdata *u = userdata;
303
304     pa_socket_client_unref(u->client);
305     u->client = NULL;
306     
307     if (!io) {
308         pa_log(__FILE__": connection failed: %s", strerror(errno));
309         cancel(u);
310         return;
311     }
312     
313     u->io = io;
314     pa_iochannel_set_callback(u->io, io_callback, u);
315 }
316
317 int pa__init(pa_core *c, pa_module*m) {
318     struct userdata *u = NULL;
319     const char *p;
320     pa_sample_spec ss;
321     pa_modargs *ma = NULL;
322     assert(c && m);
323     
324     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
325         pa_log(__FILE__": failed to parse module arguments");
326         goto fail;
327     }
328
329     ss = c->default_sample_spec;
330     if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
331         pa_log(__FILE__": invalid sample format specification");
332         goto fail;
333     }
334
335     if ((ss.format != PA_SAMPLE_U8 && ss.format != PA_SAMPLE_S16NE) ||
336         (ss.channels > 2)) {
337         pa_log(__FILE__": esound sample type support is limited to mono/stereo and U8 or S16NE sample data");
338         goto fail;
339     }
340         
341     u = pa_xmalloc0(sizeof(struct userdata));
342     u->core = c;
343     u->module = m;
344     m->userdata = u;
345     u->format =
346         (ss.format == PA_SAMPLE_U8 ? ESD_BITS8 : ESD_BITS16) |
347         (ss.channels == 2 ? ESD_STEREO : ESD_MONO);
348     u->rate = ss.rate;
349     u->sink = NULL;
350     u->client = NULL;
351     u->io = NULL;
352     u->read_data = u->write_data = NULL;
353     u->read_index = u->write_index = u->read_length = u->write_length = 0;
354     u->state = STATE_AUTH;
355     u->latency = 0;
356
357     if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
358         pa_log(__FILE__": failed to create sink.");
359         goto fail;
360     }
361
362     if (!(u->client = pa_socket_client_new_string(u->core->mainloop, p = pa_modargs_get_value(ma, "server", ESD_UNIX_SOCKET_NAME), ESD_DEFAULT_PORT))) {
363         pa_log(__FILE__": failed to connect to server.");
364         goto fail;
365     }
366     pa_socket_client_set_callback(u->client, on_connection, u);
367
368     /* Prepare the initial request */
369     u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t));
370     if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", ".esd_auth"), u->write_data, ESD_KEY_LEN) < 0) {
371         pa_log(__FILE__": failed to load cookie");
372         goto fail;
373     }
374     *(int32_t*) ((uint8_t*) u->write_data + ESD_KEY_LEN) = ESD_ENDIAN_KEY;
375
376     /* Reserve space for the response */
377     u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t));
378     
379     u->sink->notify = notify_cb;
380     u->sink->get_latency = get_latency_cb;
381     u->sink->userdata = u;
382     pa_sink_set_owner(u->sink, m);
383     u->sink->description = pa_sprintf_malloc("Esound sink '%s'", p);
384
385     u->memchunk.memblock = NULL;
386     u->memchunk.length = 0;
387
388     u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u);
389     c->mainloop->defer_enable(u->defer_event, 0);
390
391     
392     pa_modargs_free(ma);
393     
394     return 0;
395
396 fail:
397     if (ma)
398         pa_modargs_free(ma);
399         
400     pa__done(c, m);
401
402     return -1;
403 }
404
405 void pa__done(pa_core *c, pa_module*m) {
406     struct userdata *u;
407     assert(c && m);
408
409     if (!(u = m->userdata))
410         return;
411
412     u->module = NULL;
413     cancel(u);
414     
415     if (u->memchunk.memblock)
416         pa_memblock_unref(u->memchunk.memblock);
417
418     if (u->client)
419         pa_socket_client_unref(u->client);
420     
421     pa_xfree(u->read_data);
422     pa_xfree(u->write_data);
423
424     pa_xfree(u);
425 }
426
427
428