Merge HUGE set of changes temporarily into a branch, to allow me to move them from...
[profile/ivi/pulseaudio-panda.git] / src / modules / module-oss.c
1 /* $Id$ */
2
3 /***
4   This file is part of PulseAudio.
5
6   Copyright 2004-2006 Lennart Poettering
7   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9   PulseAudio is free software; you can redistribute it and/or modify
10   it under the terms of the GNU Lesser General Public License as published
11   by the Free Software Foundation; either version 2 of the License,
12   or (at your option) any later version.
13
14   PulseAudio is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with PulseAudio; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22   USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <sys/soundcard.h>
30 #include <sys/ioctl.h>
31 #include <stdlib.h>
32 #include <sys/stat.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <limits.h>
40
41 #include <pulse/xmalloc.h>
42 #include <pulse/util.h>
43
44 #include <pulsecore/core-error.h>
45 #include <pulsecore/iochannel.h>
46 #include <pulsecore/sink.h>
47 #include <pulsecore/source.h>
48 #include <pulsecore/module.h>
49 #include <pulsecore/sample-util.h>
50 #include <pulsecore/core-util.h>
51 #include <pulsecore/modargs.h>
52 #include <pulsecore/log.h>
53
54 #include "oss-util.h"
55 #include "module-oss-symdef.h"
56
57 PA_MODULE_AUTHOR("Lennart Poettering")
58 PA_MODULE_DESCRIPTION("OSS Sink/Source")
59 PA_MODULE_VERSION(PACKAGE_VERSION)
60 PA_MODULE_USAGE(
61         "sink_name=<name for the sink> "
62         "source_name=<name for the source> "
63         "device=<OSS device> "
64         "record=<enable source?> "
65         "playback=<enable sink?> "
66         "format=<sample format> "
67         "channels=<number of channels> "
68         "rate=<sample rate> "
69         "fragments=<number of fragments> "
70         "fragment_size=<fragment size> "
71         "channel_map=<channel map>")
72
73 struct userdata {
74     pa_sink *sink;
75     pa_source *source;
76     pa_iochannel *io;
77     pa_core *core;
78
79     pa_memchunk memchunk, silence;
80
81     uint32_t in_fragment_size, out_fragment_size, sample_size;
82     int use_getospace, use_getispace;
83
84     int fd;
85     pa_module *module;
86 };
87
88 static const char* const valid_modargs[] = {
89     "sink_name",
90     "source_name",
91     "device",
92     "record",
93     "playback",
94     "fragments",
95     "fragment_size",
96     "format",
97     "rate",
98     "channels",
99     "channel_map",
100     NULL
101 };
102
103 #define DEFAULT_DEVICE "/dev/dsp"
104
105 static void update_usage(struct userdata *u) {
106    pa_module_set_used(u->module,
107                       (u->sink ? pa_sink_used_by(u->sink) : 0) +
108                       (u->source ? pa_source_used_by(u->source) : 0));
109 }
110
111 static void clear_up(struct userdata *u) {
112     assert(u);
113
114     if (u->sink) {
115         pa_sink_disconnect(u->sink);
116         pa_sink_unref(u->sink);
117         u->sink = NULL;
118     }
119
120     if (u->source) {
121         pa_source_disconnect(u->source);
122         pa_source_unref(u->source);
123         u->source = NULL;
124     }
125
126     if (u->io) {
127         pa_iochannel_free(u->io);
128         u->io = NULL;
129     }
130 }
131
132 static void do_write(struct userdata *u) {
133     pa_memchunk *memchunk;
134     ssize_t r;
135     size_t l;
136     int loop = 0;
137
138     assert(u);
139
140     if (!u->sink || !pa_iochannel_is_writable(u->io))
141         return;
142
143     update_usage(u);
144
145     l = u->out_fragment_size;
146
147     if (u->use_getospace) {
148         audio_buf_info info;
149
150         if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0)
151             u->use_getospace = 0;
152         else {
153             if (info.bytes/l > 0) {
154                 l = (info.bytes/l)*l;
155                 loop = 1;
156             }
157         }
158     }
159
160     do {
161         void *p;
162         memchunk = &u->memchunk;
163
164         if (!memchunk->length)
165             if (pa_sink_render(u->sink, l, memchunk) < 0)
166                 memchunk = &u->silence;
167
168         assert(memchunk->memblock);
169         assert(memchunk->length);
170
171         p = pa_memblock_acquire(memchunk->memblock);
172         if ((r = pa_iochannel_write(u->io, (uint8_t*) p + memchunk->index, memchunk->length)) < 0) {
173             pa_memblock_release(memchunk->memblock);
174
175             if (errno != EAGAIN) {
176                 pa_log("write() failed: %s", pa_cstrerror(errno));
177
178                 clear_up(u);
179                 pa_module_unload_request(u->module);
180             }
181
182             break;
183         }
184
185         pa_memblock_release(memchunk->memblock);
186
187         if (memchunk == &u->silence)
188             assert(r % u->sample_size == 0);
189         else {
190             u->memchunk.index += r;
191             u->memchunk.length -= r;
192
193             if (u->memchunk.length <= 0) {
194                 pa_memblock_unref(u->memchunk.memblock);
195                 u->memchunk.memblock = NULL;
196             }
197         }
198
199         l = l > (size_t) r ? l - r : 0;
200     } while (loop && l > 0);
201 }
202
203 static void do_read(struct userdata *u) {
204     pa_memchunk memchunk;
205     ssize_t r;
206     size_t l;
207     int loop = 0;
208     assert(u);
209
210     if (!u->source || !pa_iochannel_is_readable(u->io) || !pa_idxset_size(u->source->outputs))
211         return;
212
213     update_usage(u);
214
215     l = u->in_fragment_size;
216
217     if (u->use_getispace) {
218         audio_buf_info info;
219
220         if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0)
221             u->use_getispace = 0;
222         else {
223             if (info.bytes/l > 0) {
224                 l = (info.bytes/l)*l;
225                 loop = 1;
226             }
227         }
228     }
229
230     do {
231         void *p;
232         memchunk.memblock = pa_memblock_new(u->core->mempool, l);
233
234         p = pa_memblock_acquire(memchunk.memblock);
235
236         if ((r = pa_iochannel_read(u->io, p, pa_memblock_get_length(memchunk.memblock))) < 0) {
237             pa_memblock_release(memchunk.memblock);
238             pa_memblock_unref(memchunk.memblock);
239
240             if (errno != EAGAIN) {
241                 pa_log("read() failed: %s", pa_cstrerror(errno));
242
243                 clear_up(u);
244                 pa_module_unload_request(u->module);
245             }
246
247             break;
248         }
249
250         pa_memblock_release(memchunk.memblock);
251
252         assert(r <= (ssize_t) pa_memblock_get_length(memchunk.memblock));
253         memchunk.length = r;
254         memchunk.index = 0;
255
256         pa_source_post(u->source, &memchunk);
257         pa_memblock_unref(memchunk.memblock);
258
259         l = l > (size_t) r ? l - r : 0;
260     } while (loop && l > 0);
261 }
262
263 static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
264     struct userdata *u = userdata;
265     assert(u);
266     do_write(u);
267     do_read(u);
268 }
269
270 static void source_notify_cb(pa_source *s) {
271     struct userdata *u = s->userdata;
272     assert(u);
273     do_read(u);
274 }
275
276 static pa_usec_t sink_get_latency_cb(pa_sink *s) {
277     pa_usec_t r = 0;
278     int arg;
279     struct userdata *u = s->userdata;
280     assert(s && u && u->sink);
281
282     if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
283         pa_log_info("device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno));
284         s->get_latency = NULL;
285         return 0;
286     }
287
288     r += pa_bytes_to_usec(arg, &s->sample_spec);
289
290     if (u->memchunk.memblock)
291         r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
292
293     return r;
294 }
295
296 static pa_usec_t source_get_latency_cb(pa_source *s) {
297     struct userdata *u = s->userdata;
298     audio_buf_info info;
299     assert(s && u && u->source);
300
301     if (!u->use_getispace)
302         return 0;
303
304     if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
305         u->use_getispace = 0;
306         return 0;
307     }
308
309     if (info.bytes <= 0)
310         return 0;
311
312     return pa_bytes_to_usec(info.bytes, &s->sample_spec);
313 }
314
315 static int sink_get_hw_volume(pa_sink *s) {
316     struct userdata *u = s->userdata;
317
318     if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
319         pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
320         s->get_hw_volume = NULL;
321         return -1;
322     }
323
324     return 0;
325 }
326
327 static int sink_set_hw_volume(pa_sink *s) {
328     struct userdata *u = s->userdata;
329
330     if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
331         pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
332         s->set_hw_volume = NULL;
333         return -1;
334     }
335
336     return 0;
337 }
338
339 static int source_get_hw_volume(pa_source *s) {
340     struct userdata *u = s->userdata;
341
342     if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
343         pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
344         s->get_hw_volume = NULL;
345         return -1;
346     }
347
348     return 0;
349 }
350
351 static int source_set_hw_volume(pa_source *s) {
352     struct userdata *u = s->userdata;
353
354     if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
355         pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
356         s->set_hw_volume = NULL;
357         return -1;
358     }
359
360     return 0;
361 }
362
363 int pa__init(pa_core *c, pa_module*m) {
364     struct audio_buf_info info;
365     struct userdata *u = NULL;
366     const char *p;
367     int fd = -1;
368     int nfrags, frag_size, in_frag_size, out_frag_size;
369     int mode;
370     int record = 1, playback = 1;
371     pa_sample_spec ss;
372     pa_channel_map map;
373     pa_modargs *ma = NULL;
374     char hwdesc[64], *t;
375     const char *name;
376     char *name_buf = NULL;
377     int namereg_fail;
378
379     assert(c);
380     assert(m);
381
382     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
383         pa_log("failed to parse module arguments.");
384         goto fail;
385     }
386
387     if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
388         pa_log("record= and playback= expect numeric argument.");
389         goto fail;
390     }
391
392     if (!playback && !record) {
393         pa_log("neither playback nor record enabled for device.");
394         goto fail;
395     }
396
397     mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
398
399     ss = c->default_sample_spec;
400     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_OSS) < 0) {
401         pa_log("failed to parse sample specification or channel map");
402         goto fail;
403     }
404
405     /* Fix latency to 100ms */
406     nfrags = 12;
407     frag_size = pa_bytes_per_second(&ss)/128;
408
409     if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
410         pa_log("failed to parse fragments arguments");
411         goto fail;
412     }
413
414     if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0)
415         goto fail;
416
417     if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0)
418         pa_log_info("hardware name is '%s'.", hwdesc);
419     else
420         hwdesc[0] = 0;
421
422     pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
423
424     if (nfrags >= 2 && frag_size >= 1)
425         if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0)
426             goto fail;
427
428     if (pa_oss_auto_format(fd, &ss) < 0)
429         goto fail;
430
431     if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) {
432         pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
433         goto fail;
434     }
435     assert(frag_size);
436     in_frag_size = out_frag_size = frag_size;
437
438     u = pa_xmalloc(sizeof(struct userdata));
439     u->core = c;
440     u->use_getospace = u->use_getispace = 0;
441
442     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
443         pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
444         in_frag_size = info.fragsize;
445         u->use_getispace = 1;
446     }
447
448     if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
449         pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
450         out_frag_size = info.fragsize;
451         u->use_getospace = 1;
452     }
453
454     if (mode != O_WRONLY) {
455         if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
456             namereg_fail = 1;
457         else {
458             name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p));
459             namereg_fail = 0;
460         }
461
462         if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map)))
463             goto fail;
464
465         u->source->userdata = u;
466         u->source->notify = source_notify_cb;
467         u->source->get_latency = source_get_latency_cb;
468         u->source->get_hw_volume = source_get_hw_volume;
469         u->source->set_hw_volume = source_set_hw_volume;
470         pa_source_set_owner(u->source, m);
471         pa_source_set_description(u->source, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s",
472                                                                  p,
473                                                                  hwdesc[0] ? " (" : "",
474                                                                  hwdesc[0] ? hwdesc : "",
475                                                                  hwdesc[0] ? ")" : ""));
476         pa_xfree(t);
477         u->source->is_hardware = 1;
478     } else
479         u->source = NULL;
480
481     pa_xfree(name_buf);
482     name_buf = NULL;
483
484     if (mode != O_RDONLY) {
485         if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
486             namereg_fail = 1;
487         else {
488             name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p));
489             namereg_fail = 0;
490         }
491
492         if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map)))
493             goto fail;
494
495         u->sink->get_latency = sink_get_latency_cb;
496         u->sink->get_hw_volume = sink_get_hw_volume;
497         u->sink->set_hw_volume = sink_set_hw_volume;
498         u->sink->userdata = u;
499         pa_sink_set_owner(u->sink, m);
500         pa_sink_set_description(u->sink, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s",
501                                                            p,
502                                                            hwdesc[0] ? " (" : "",
503                                                            hwdesc[0] ? hwdesc : "",
504                                                            hwdesc[0] ? ")" : ""));
505         pa_xfree(t);
506         u->sink->is_hardware = 1;
507     } else
508         u->sink = NULL;
509
510     pa_xfree(name_buf);
511     name_buf = NULL;
512
513     assert(u->source || u->sink);
514
515     u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : -1);
516     assert(u->io);
517     pa_iochannel_set_callback(u->io, io_callback, u);
518     u->fd = fd;
519
520     u->memchunk.memblock = NULL;
521     u->memchunk.length = 0;
522     u->sample_size = pa_frame_size(&ss);
523
524     u->out_fragment_size = out_frag_size;
525     u->in_fragment_size = in_frag_size;
526     u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = u->out_fragment_size);
527     assert(u->silence.memblock);
528     pa_silence_memblock(u->silence.memblock, &ss);
529     u->silence.index = 0;
530
531     u->module = m;
532     m->userdata = u;
533
534     pa_modargs_free(ma);
535
536     /*
537      * Some crappy drivers do not start the recording until we read something.
538      * Without this snippet, poll will never register the fd as ready.
539      */
540     if (u->source) {
541         char *buf = pa_xnew(char, u->sample_size);
542         pa_read(u->fd, buf, u->sample_size, NULL);
543         pa_xfree(buf);
544     }
545
546     /* Read mixer settings */
547     if (u->source)
548         source_get_hw_volume(u->source);
549     if (u->sink)
550         sink_get_hw_volume(u->sink);
551
552     return 0;
553
554 fail:
555     if (fd >= 0)
556         close(fd);
557
558     if (ma)
559         pa_modargs_free(ma);
560
561     pa_xfree(name_buf);
562
563     return -1;
564 }
565
566 void pa__done(pa_core *c, pa_module*m) {
567     struct userdata *u;
568
569     assert(c);
570     assert(m);
571
572     if (!(u = m->userdata))
573         return;
574
575     clear_up(u);
576
577     if (u->memchunk.memblock)
578         pa_memblock_unref(u->memchunk.memblock);
579     if (u->silence.memblock)
580         pa_memblock_unref(u->silence.memblock);
581
582     pa_xfree(u);
583 }