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