9d4d0eac12b78edeba875f2b9923181417e7c5aa
[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         memchunk = &u->memchunk;
162
163         if (!memchunk->length)
164             if (pa_sink_render(u->sink, l, memchunk) < 0)
165                 memchunk = &u->silence;
166
167         assert(memchunk->memblock);
168         assert(memchunk->memblock->data);
169         assert(memchunk->length);
170
171         if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) {
172
173             if (errno != EAGAIN) {
174                 pa_log("write() failed: %s", pa_cstrerror(errno));
175
176                 clear_up(u);
177                 pa_module_unload_request(u->module);
178             }
179
180             break;
181         }
182
183         if (memchunk == &u->silence)
184             assert(r % u->sample_size == 0);
185         else {
186             u->memchunk.index += r;
187             u->memchunk.length -= r;
188
189             if (u->memchunk.length <= 0) {
190                 pa_memblock_unref(u->memchunk.memblock);
191                 u->memchunk.memblock = NULL;
192             }
193         }
194
195         l = l > (size_t) r ? l - r : 0;
196     } while (loop && l > 0);
197 }
198
199 static void do_read(struct userdata *u) {
200     pa_memchunk memchunk;
201     ssize_t r;
202     size_t l;
203     int loop = 0;
204     assert(u);
205
206     if (!u->source || !pa_iochannel_is_readable(u->io) || !pa_idxset_size(u->source->outputs))
207         return;
208
209     update_usage(u);
210
211     l = u->in_fragment_size;
212
213     if (u->use_getispace) {
214         audio_buf_info info;
215
216         if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0)
217             u->use_getispace = 0;
218         else {
219             if (info.bytes/l > 0) {
220                 l = (info.bytes/l)*l;
221                 loop = 1;
222             }
223         }
224     }
225
226     do {
227         memchunk.memblock = pa_memblock_new(u->core->mempool, l);
228         assert(memchunk.memblock);
229         if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) {
230             pa_memblock_unref(memchunk.memblock);
231
232             if (errno != EAGAIN) {
233                 pa_log("read() failed: %s", pa_cstrerror(errno));
234
235                 clear_up(u);
236                 pa_module_unload_request(u->module);
237             }
238
239             break;
240         }
241
242         assert(r <= (ssize_t) memchunk.memblock->length);
243         memchunk.length = memchunk.memblock->length = r;
244         memchunk.index = 0;
245
246         pa_source_post(u->source, &memchunk);
247         pa_memblock_unref(memchunk.memblock);
248
249         l = l > (size_t) r ? l - r : 0;
250     } while (loop && l > 0);
251 }
252
253 static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
254     struct userdata *u = userdata;
255     assert(u);
256     do_write(u);
257     do_read(u);
258 }
259
260 static void source_notify_cb(pa_source *s) {
261     struct userdata *u = s->userdata;
262     assert(u);
263     do_read(u);
264 }
265
266 static pa_usec_t sink_get_latency_cb(pa_sink *s) {
267     pa_usec_t r = 0;
268     int arg;
269     struct userdata *u = s->userdata;
270     assert(s && u && u->sink);
271
272     if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
273         pa_log_info("device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno));
274         s->get_latency = NULL;
275         return 0;
276     }
277
278     r += pa_bytes_to_usec(arg, &s->sample_spec);
279
280     if (u->memchunk.memblock)
281         r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
282
283     return r;
284 }
285
286 static pa_usec_t source_get_latency_cb(pa_source *s) {
287     struct userdata *u = s->userdata;
288     audio_buf_info info;
289     assert(s && u && u->source);
290
291     if (!u->use_getispace)
292         return 0;
293
294     if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
295         u->use_getispace = 0;
296         return 0;
297     }
298
299     if (info.bytes <= 0)
300         return 0;
301
302     return pa_bytes_to_usec(info.bytes, &s->sample_spec);
303 }
304
305 static int sink_get_hw_volume(pa_sink *s) {
306     struct userdata *u = s->userdata;
307
308     if (pa_oss_get_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
309         pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
310         s->get_hw_volume = NULL;
311         return -1;
312     }
313
314     return 0;
315 }
316
317 static int sink_set_hw_volume(pa_sink *s) {
318     struct userdata *u = s->userdata;
319
320     if (pa_oss_set_pcm_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
321         pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
322         s->set_hw_volume = NULL;
323         return -1;
324     }
325
326     return 0;
327 }
328
329 static int source_get_hw_volume(pa_source *s) {
330     struct userdata *u = s->userdata;
331
332     if (pa_oss_get_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
333         pa_log_info("device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
334         s->get_hw_volume = NULL;
335         return -1;
336     }
337
338     return 0;
339 }
340
341 static int source_set_hw_volume(pa_source *s) {
342     struct userdata *u = s->userdata;
343
344     if (pa_oss_set_input_volume(u->fd, &s->sample_spec, &s->hw_volume) < 0) {
345         pa_log_info("device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
346         s->set_hw_volume = NULL;
347         return -1;
348     }
349
350     return 0;
351 }
352
353 int pa__init(pa_core *c, pa_module*m) {
354     struct audio_buf_info info;
355     struct userdata *u = NULL;
356     const char *p;
357     int fd = -1;
358     int nfrags, frag_size, in_frag_size, out_frag_size;
359     int mode;
360     int record = 1, playback = 1;
361     pa_sample_spec ss;
362     pa_channel_map map;
363     pa_modargs *ma = NULL;
364     char hwdesc[64], *t;
365     const char *name;
366     char *name_buf = NULL;
367     int namereg_fail;
368
369     assert(c);
370     assert(m);
371
372     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
373         pa_log("failed to parse module arguments.");
374         goto fail;
375     }
376
377     if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
378         pa_log("record= and playback= expect numeric argument.");
379         goto fail;
380     }
381
382     if (!playback && !record) {
383         pa_log("neither playback nor record enabled for device.");
384         goto fail;
385     }
386
387     mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
388
389     ss = c->default_sample_spec;
390     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_OSS) < 0) {
391         pa_log("failed to parse sample specification or channel map");
392         goto fail;
393     }
394
395     /* Fix latency to 100ms */
396     nfrags = 12;
397     frag_size = pa_bytes_per_second(&ss)/128;
398
399     if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
400         pa_log("failed to parse fragments arguments");
401         goto fail;
402     }
403
404     if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, NULL)) < 0)
405         goto fail;
406
407     if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0)
408         pa_log_info("hardware name is '%s'.", hwdesc);
409     else
410         hwdesc[0] = 0;
411
412     pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
413
414     if (nfrags >= 2 && frag_size >= 1)
415         if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0)
416             goto fail;
417
418     if (pa_oss_auto_format(fd, &ss) < 0)
419         goto fail;
420
421     if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) {
422         pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
423         goto fail;
424     }
425     assert(frag_size);
426     in_frag_size = out_frag_size = frag_size;
427
428     u = pa_xmalloc(sizeof(struct userdata));
429     u->core = c;
430     u->use_getospace = u->use_getispace = 0;
431
432     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
433         pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
434         in_frag_size = info.fragsize;
435         u->use_getispace = 1;
436     }
437
438     if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
439         pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
440         out_frag_size = info.fragsize;
441         u->use_getospace = 1;
442     }
443
444     if (mode != O_WRONLY) {
445         if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
446             namereg_fail = 1;
447         else {
448             name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p));
449             namereg_fail = 0;
450         }
451
452         if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map)))
453             goto fail;
454
455         u->source->userdata = u;
456         u->source->notify = source_notify_cb;
457         u->source->get_latency = source_get_latency_cb;
458         u->source->get_hw_volume = source_get_hw_volume;
459         u->source->set_hw_volume = source_set_hw_volume;
460         pa_source_set_owner(u->source, m);
461         pa_source_set_description(u->source, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s",
462                                                                  p,
463                                                                  hwdesc[0] ? " (" : "",
464                                                                  hwdesc[0] ? hwdesc : "",
465                                                                  hwdesc[0] ? ")" : ""));
466         pa_xfree(t);
467         u->source->is_hardware = 1;
468     } else
469         u->source = NULL;
470
471     pa_xfree(name_buf);
472     name_buf = NULL;
473
474     if (mode != O_RDONLY) {
475         if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
476             namereg_fail = 1;
477         else {
478             name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p));
479             namereg_fail = 0;
480         }
481
482         if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map)))
483             goto fail;
484
485         u->sink->get_latency = sink_get_latency_cb;
486         u->sink->get_hw_volume = sink_get_hw_volume;
487         u->sink->set_hw_volume = sink_set_hw_volume;
488         u->sink->userdata = u;
489         pa_sink_set_owner(u->sink, m);
490         pa_sink_set_description(u->sink, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s",
491                                                            p,
492                                                            hwdesc[0] ? " (" : "",
493                                                            hwdesc[0] ? hwdesc : "",
494                                                            hwdesc[0] ? ")" : ""));
495         pa_xfree(t);
496         u->sink->is_hardware = 1;
497     } else
498         u->sink = NULL;
499
500     pa_xfree(name_buf);
501     name_buf = NULL;
502
503     assert(u->source || u->sink);
504
505     u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : -1);
506     assert(u->io);
507     pa_iochannel_set_callback(u->io, io_callback, u);
508     u->fd = fd;
509
510     u->memchunk.memblock = NULL;
511     u->memchunk.length = 0;
512     u->sample_size = pa_frame_size(&ss);
513
514     u->out_fragment_size = out_frag_size;
515     u->in_fragment_size = in_frag_size;
516     u->silence.memblock = pa_memblock_new(u->core->mempool, u->silence.length = u->out_fragment_size);
517     assert(u->silence.memblock);
518     pa_silence_memblock(u->silence.memblock, &ss);
519     u->silence.index = 0;
520
521     u->module = m;
522     m->userdata = u;
523
524     pa_modargs_free(ma);
525
526     /*
527      * Some crappy drivers do not start the recording until we read something.
528      * Without this snippet, poll will never register the fd as ready.
529      */
530     if (u->source) {
531         char *buf = pa_xnew(char, u->sample_size);
532         pa_read(u->fd, buf, u->sample_size, NULL);
533         pa_xfree(buf);
534     }
535
536     /* Read mixer settings */
537     if (u->source)
538         source_get_hw_volume(u->source);
539     if (u->sink)
540         sink_get_hw_volume(u->sink);
541
542     return 0;
543
544 fail:
545     if (fd >= 0)
546         close(fd);
547
548     if (ma)
549         pa_modargs_free(ma);
550
551     pa_xfree(name_buf);
552
553     return -1;
554 }
555
556 void pa__done(pa_core *c, pa_module*m) {
557     struct userdata *u;
558
559     assert(c);
560     assert(m);
561
562     if (!(u = m->userdata))
563         return;
564
565     clear_up(u);
566
567     if (u->memchunk.memblock)
568         pa_memblock_unref(u->memchunk.memblock);
569     if (u->silence.memblock)
570         pa_memblock_unref(u->silence.memblock);
571
572     pa_xfree(u);
573 }