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