Git init
[framework/multimedia/pulseaudio.git] / src / modules / oss / module-oss.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20   USA.
21 ***/
22
23 /* General power management rules:
24  *
25  *   When SUSPENDED we close the audio device.
26  *
27  *   We make no difference between IDLE and RUNNING in our handling.
28  *
29  *   As long as we are in RUNNING/IDLE state we will *always* write data to
30  *   the device. If none is avilable from the inputs, we write silence
31  *   instead.
32  *
33  *   If power should be saved on IDLE module-suspend-on-idle should be used.
34  *
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifdef HAVE_SYS_MMAN_H
42 #include <sys/mman.h>
43 #endif
44
45 #include <sys/soundcard.h>
46 #include <sys/ioctl.h>
47 #include <stdlib.h>
48 #include <sys/stat.h>
49 #include <stdio.h>
50 #include <errno.h>
51 #include <string.h>
52 #include <fcntl.h>
53 #include <unistd.h>
54 #include <limits.h>
55 #include <signal.h>
56 #include <poll.h>
57
58 #include <pulse/xmalloc.h>
59 #include <pulse/util.h>
60
61 #include <pulsecore/core-error.h>
62 #include <pulsecore/thread.h>
63 #include <pulsecore/sink.h>
64 #include <pulsecore/source.h>
65 #include <pulsecore/module.h>
66 #include <pulsecore/sample-util.h>
67 #include <pulsecore/core-util.h>
68 #include <pulsecore/modargs.h>
69 #include <pulsecore/log.h>
70 #include <pulsecore/macro.h>
71 #include <pulsecore/thread-mq.h>
72 #include <pulsecore/rtpoll.h>
73
74 #if defined(__NetBSD__) && !defined(SNDCTL_DSP_GETODELAY)
75 #include <sys/audioio.h>
76 #include <sys/syscall.h>
77 #endif
78
79 #include "oss-util.h"
80 #include "module-oss-symdef.h"
81
82 PA_MODULE_AUTHOR("Lennart Poettering");
83 PA_MODULE_DESCRIPTION("OSS Sink/Source");
84 PA_MODULE_VERSION(PACKAGE_VERSION);
85 PA_MODULE_LOAD_ONCE(FALSE);
86 PA_MODULE_USAGE(
87         "sink_name=<name for the sink> "
88         "sink_properties=<properties for the sink> "
89         "source_name=<name for the source> "
90         "source_properties=<properties for the source> "
91         "device=<OSS device> "
92         "record=<enable source?> "
93         "playback=<enable sink?> "
94         "format=<sample format> "
95         "rate=<sample rate> "
96         "channels=<number of channels> "
97         "channel_map=<channel map> "
98         "fragments=<number of fragments> "
99         "fragment_size=<fragment size> "
100         "mmap=<enable memory mapping?>");
101 #ifdef __linux__
102 PA_MODULE_DEPRECATED("Please use module-alsa-card instead of module-oss!");
103 #endif
104
105 #define DEFAULT_DEVICE "/dev/dsp"
106
107 struct userdata {
108     pa_core *core;
109     pa_module *module;
110     pa_sink *sink;
111     pa_source *source;
112
113     pa_thread *thread;
114     pa_thread_mq thread_mq;
115     pa_rtpoll *rtpoll;
116
117     char *device_name;
118
119     pa_memchunk memchunk;
120
121     size_t frame_size;
122     uint32_t in_fragment_size, out_fragment_size, in_nfrags, out_nfrags, in_hwbuf_size, out_hwbuf_size;
123     pa_bool_t use_getospace, use_getispace;
124     pa_bool_t use_getodelay;
125
126     pa_bool_t sink_suspended, source_suspended;
127
128     int fd;
129     int mode;
130
131     int mixer_fd;
132     int mixer_devmask;
133
134     int nfrags, frag_size, orig_frag_size;
135
136     pa_bool_t use_mmap;
137     unsigned out_mmap_current, in_mmap_current;
138     void *in_mmap, *out_mmap;
139     pa_memblock **in_mmap_memblocks, **out_mmap_memblocks;
140
141     int in_mmap_saved_nfrags, out_mmap_saved_nfrags;
142
143     pa_rtpoll_item *rtpoll_item;
144 };
145
146 static const char* const valid_modargs[] = {
147     "sink_name",
148     "sink_properties",
149     "source_name",
150     "source_properties",
151     "device",
152     "record",
153     "playback",
154     "fragments",
155     "fragment_size",
156     "format",
157     "rate",
158     "channels",
159     "channel_map",
160     "mmap",
161     NULL
162 };
163
164 static void trigger(struct userdata *u, pa_bool_t quick) {
165     int enable_bits = 0, zero = 0;
166
167     pa_assert(u);
168
169     if (u->fd < 0)
170         return;
171
172      pa_log_debug("trigger");
173
174     if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state))
175         enable_bits |= PCM_ENABLE_INPUT;
176
177     if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state))
178         enable_bits |= PCM_ENABLE_OUTPUT;
179
180     pa_log_debug("trigger: %i", enable_bits);
181
182
183     if (u->use_mmap) {
184
185         if (!quick)
186             ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero);
187
188 #ifdef SNDCTL_DSP_HALT
189         if (enable_bits == 0)
190             if (ioctl(u->fd, SNDCTL_DSP_HALT, NULL) < 0)
191                 pa_log_warn("SNDCTL_DSP_HALT: %s", pa_cstrerror(errno));
192 #endif
193
194         if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0)
195             pa_log_warn("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));
196
197         if (u->sink && !(enable_bits & PCM_ENABLE_OUTPUT)) {
198             pa_log_debug("clearing playback buffer");
199             pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &u->sink->sample_spec);
200         }
201
202     } else {
203
204         if (enable_bits)
205             if (ioctl(u->fd, SNDCTL_DSP_POST, NULL) < 0)
206                 pa_log_warn("SNDCTL_DSP_POST: %s", pa_cstrerror(errno));
207
208         if (!quick) {
209             /*
210              * Some crappy drivers do not start the recording until we
211              * read something.  Without this snippet, poll will never
212              * register the fd as ready.
213              */
214
215             if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
216                 uint8_t *buf = pa_xnew(uint8_t, u->in_fragment_size);
217                 pa_read(u->fd, buf, u->in_fragment_size, NULL);
218                 pa_xfree(buf);
219             }
220         }
221     }
222 }
223
224 static void mmap_fill_memblocks(struct userdata *u, unsigned n) {
225     pa_assert(u);
226     pa_assert(u->out_mmap_memblocks);
227
228 /*     pa_log("Mmmap writing %u blocks", n); */
229
230     while (n > 0) {
231         pa_memchunk chunk;
232
233         if (u->out_mmap_memblocks[u->out_mmap_current])
234             pa_memblock_unref_fixed(u->out_mmap_memblocks[u->out_mmap_current]);
235
236         chunk.memblock = u->out_mmap_memblocks[u->out_mmap_current] =
237             pa_memblock_new_fixed(
238                     u->core->mempool,
239                     (uint8_t*) u->out_mmap + u->out_fragment_size * u->out_mmap_current,
240                     u->out_fragment_size,
241                     1);
242
243         chunk.length = pa_memblock_get_length(chunk.memblock);
244         chunk.index = 0;
245
246         pa_sink_render_into_full(u->sink, &chunk);
247
248         u->out_mmap_current++;
249         while (u->out_mmap_current >= u->out_nfrags)
250             u->out_mmap_current -= u->out_nfrags;
251
252         n--;
253     }
254 }
255
256 static int mmap_write(struct userdata *u) {
257     struct count_info info;
258
259     pa_assert(u);
260     pa_assert(u->sink);
261
262 /*     pa_log("Mmmap writing..."); */
263
264     if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
265         pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno));
266         return -1;
267     }
268
269     info.blocks += u->out_mmap_saved_nfrags;
270     u->out_mmap_saved_nfrags = 0;
271
272     if (info.blocks > 0)
273         mmap_fill_memblocks(u, (unsigned) info.blocks);
274
275     return info.blocks;
276 }
277
278 static void mmap_post_memblocks(struct userdata *u, unsigned n) {
279     pa_assert(u);
280     pa_assert(u->in_mmap_memblocks);
281
282 /*     pa_log("Mmmap reading %u blocks", n); */
283
284     while (n > 0) {
285         pa_memchunk chunk;
286
287         if (!u->in_mmap_memblocks[u->in_mmap_current]) {
288
289             chunk.memblock = u->in_mmap_memblocks[u->in_mmap_current] =
290                 pa_memblock_new_fixed(
291                         u->core->mempool,
292                         (uint8_t*) u->in_mmap + u->in_fragment_size*u->in_mmap_current,
293                         u->in_fragment_size,
294                         1);
295
296             chunk.length = pa_memblock_get_length(chunk.memblock);
297             chunk.index = 0;
298
299             pa_source_post(u->source, &chunk);
300         }
301
302         u->in_mmap_current++;
303         while (u->in_mmap_current >= u->in_nfrags)
304             u->in_mmap_current -= u->in_nfrags;
305
306         n--;
307     }
308 }
309
310 static void mmap_clear_memblocks(struct userdata*u, unsigned n) {
311     unsigned i = u->in_mmap_current;
312
313     pa_assert(u);
314     pa_assert(u->in_mmap_memblocks);
315
316     if (n > u->in_nfrags)
317         n = u->in_nfrags;
318
319     while (n > 0) {
320         if (u->in_mmap_memblocks[i]) {
321             pa_memblock_unref_fixed(u->in_mmap_memblocks[i]);
322             u->in_mmap_memblocks[i] = NULL;
323         }
324
325         i++;
326         while (i >= u->in_nfrags)
327             i -= u->in_nfrags;
328
329         n--;
330     }
331 }
332
333 static int mmap_read(struct userdata *u) {
334     struct count_info info;
335     pa_assert(u);
336     pa_assert(u->source);
337
338 /*     pa_log("Mmmap reading..."); */
339
340     if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
341         pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
342         return -1;
343     }
344
345 /*     pa_log("... %i", info.blocks); */
346
347     info.blocks += u->in_mmap_saved_nfrags;
348     u->in_mmap_saved_nfrags = 0;
349
350     if (info.blocks > 0) {
351         mmap_post_memblocks(u, (unsigned) info.blocks);
352         mmap_clear_memblocks(u, u->in_nfrags/2);
353     }
354
355     return info.blocks;
356 }
357
358 static pa_usec_t mmap_sink_get_latency(struct userdata *u) {
359     struct count_info info;
360     size_t bpos, n;
361
362     pa_assert(u);
363
364     if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
365         pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno));
366         return 0;
367     }
368
369     u->out_mmap_saved_nfrags += info.blocks;
370
371     bpos = ((u->out_mmap_current + (unsigned) u->out_mmap_saved_nfrags) * u->out_fragment_size) % u->out_hwbuf_size;
372
373     if (bpos <= (size_t) info.ptr)
374         n = u->out_hwbuf_size - ((size_t) info.ptr - bpos);
375     else
376         n = bpos - (size_t) info.ptr;
377
378 /*     pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */
379
380     return pa_bytes_to_usec(n, &u->sink->sample_spec);
381 }
382
383 static pa_usec_t mmap_source_get_latency(struct userdata *u) {
384     struct count_info info;
385     size_t bpos, n;
386
387     pa_assert(u);
388
389     if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
390         pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
391         return 0;
392     }
393
394     u->in_mmap_saved_nfrags += info.blocks;
395     bpos = ((u->in_mmap_current + (unsigned) u->in_mmap_saved_nfrags) * u->in_fragment_size) % u->in_hwbuf_size;
396
397     if (bpos <= (size_t) info.ptr)
398         n = (size_t) info.ptr - bpos;
399     else
400         n = u->in_hwbuf_size - bpos + (size_t) info.ptr;
401
402 /*     pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments);  */
403
404     return pa_bytes_to_usec(n, &u->source->sample_spec);
405 }
406
407 static pa_usec_t io_sink_get_latency(struct userdata *u) {
408     pa_usec_t r = 0;
409
410     pa_assert(u);
411
412     if (u->use_getodelay) {
413         int arg;
414 #if defined(__NetBSD__) && !defined(SNDCTL_DSP_GETODELAY)
415 #if defined(AUDIO_GETBUFINFO)
416         struct audio_info info;
417         if (syscall(SYS_ioctl, u->fd, AUDIO_GETBUFINFO, &info) < 0) {
418             pa_log_info("Device doesn't support AUDIO_GETBUFINFO: %s", pa_cstrerror(errno));
419             u->use_getodelay = 0;
420         } else {
421             arg = info.play.seek + info.blocksize / 2;
422             r = pa_bytes_to_usec((size_t) arg, &u->sink->sample_spec);
423         }
424 #else
425         pa_log_info("System doesn't support AUDIO_GETBUFINFO");
426         u->use_getodelay = 0;
427 #endif
428 #else
429         if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
430             pa_log_info("Device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno));
431             u->use_getodelay = 0;
432         } else
433             r = pa_bytes_to_usec((size_t) arg, &u->sink->sample_spec);
434 #endif
435     }
436
437     if (!u->use_getodelay && u->use_getospace) {
438         struct audio_buf_info info;
439
440         if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
441             pa_log_info("Device doesn't support SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno));
442             u->use_getospace = 0;
443         } else
444             r = pa_bytes_to_usec((size_t) info.bytes, &u->sink->sample_spec);
445     }
446
447     if (u->memchunk.memblock)
448         r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
449
450     return r;
451 }
452
453 static pa_usec_t io_source_get_latency(struct userdata *u) {
454     pa_usec_t r = 0;
455
456     pa_assert(u);
457
458     if (u->use_getispace) {
459         struct audio_buf_info info;
460
461         if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
462             pa_log_info("Device doesn't support SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno));
463             u->use_getispace = 0;
464         } else
465             r = pa_bytes_to_usec((size_t) info.bytes, &u->source->sample_spec);
466     }
467
468     return r;
469 }
470
471 static void build_pollfd(struct userdata *u) {
472     struct pollfd *pollfd;
473
474     pa_assert(u);
475     pa_assert(u->fd >= 0);
476
477     if (u->rtpoll_item)
478         pa_rtpoll_item_free(u->rtpoll_item);
479
480     u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
481     pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
482     pollfd->fd = u->fd;
483     pollfd->events = 0;
484     pollfd->revents = 0;
485 }
486
487 /* Called from IO context */
488 static int suspend(struct userdata *u) {
489     pa_assert(u);
490     pa_assert(u->fd >= 0);
491
492     pa_log_info("Suspending...");
493
494     if (u->out_mmap_memblocks) {
495         unsigned i;
496         for (i = 0; i < u->out_nfrags; i++)
497             if (u->out_mmap_memblocks[i]) {
498                 pa_memblock_unref_fixed(u->out_mmap_memblocks[i]);
499                 u->out_mmap_memblocks[i] = NULL;
500             }
501     }
502
503     if (u->in_mmap_memblocks) {
504         unsigned i;
505         for (i = 0; i < u->in_nfrags; i++)
506             if (u->in_mmap_memblocks[i]) {
507                 pa_memblock_unref_fixed(u->in_mmap_memblocks[i]);
508                 u->in_mmap_memblocks[i] = NULL;
509             }
510     }
511
512     if (u->in_mmap && u->in_mmap != MAP_FAILED) {
513         munmap(u->in_mmap, u->in_hwbuf_size);
514         u->in_mmap = NULL;
515     }
516
517     if (u->out_mmap && u->out_mmap != MAP_FAILED) {
518         munmap(u->out_mmap, u->out_hwbuf_size);
519         u->out_mmap = NULL;
520     }
521
522     /* Let's suspend */
523     ioctl(u->fd, SNDCTL_DSP_SYNC, NULL);
524     pa_close(u->fd);
525     u->fd = -1;
526
527     if (u->rtpoll_item) {
528         pa_rtpoll_item_free(u->rtpoll_item);
529         u->rtpoll_item = NULL;
530     }
531
532     pa_log_info("Device suspended...");
533
534     return 0;
535 }
536
537 /* Called from IO context */
538 static int unsuspend(struct userdata *u) {
539     int m;
540     pa_sample_spec ss, *ss_original;
541     int frag_size, in_frag_size, out_frag_size;
542     int in_nfrags, out_nfrags;
543     struct audio_buf_info info;
544
545     pa_assert(u);
546     pa_assert(u->fd < 0);
547
548     m = u->mode;
549
550     pa_log_info("Trying resume...");
551
552     if ((u->fd = pa_oss_open(u->device_name, &m, NULL)) < 0) {
553         pa_log_warn("Resume failed, device busy (%s)", pa_cstrerror(errno));
554         return -1;
555     }
556
557     if (m != u->mode) {
558         pa_log_warn("Resume failed, couldn't open device with original access mode.");
559         goto fail;
560     }
561
562     if (u->nfrags >= 2 && u->frag_size >= 1)
563         if (pa_oss_set_fragments(u->fd, u->nfrags, u->orig_frag_size) < 0) {
564             pa_log_warn("Resume failed, couldn't set original fragment settings.");
565             goto fail;
566         }
567
568     ss = *(ss_original = u->sink ? &u->sink->sample_spec : &u->source->sample_spec);
569     if (pa_oss_auto_format(u->fd, &ss) < 0 || !pa_sample_spec_equal(&ss, ss_original)) {
570         pa_log_warn("Resume failed, couldn't set original sample format settings.");
571         goto fail;
572     }
573
574     if (ioctl(u->fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) {
575         pa_log_warn("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
576         goto fail;
577     }
578
579     in_frag_size = out_frag_size = frag_size;
580     in_nfrags = out_nfrags = u->nfrags;
581
582     if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
583         in_frag_size = info.fragsize;
584         in_nfrags = info.fragstotal;
585     }
586
587     if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
588         out_frag_size = info.fragsize;
589         out_nfrags = info.fragstotal;
590     }
591
592     if ((u->source && (in_frag_size != (int) u->in_fragment_size || in_nfrags != (int) u->in_nfrags)) ||
593         (u->sink && (out_frag_size != (int) u->out_fragment_size || out_nfrags != (int) u->out_nfrags))) {
594         pa_log_warn("Resume failed, input fragment settings don't match.");
595         goto fail;
596     }
597
598     if (u->use_mmap) {
599         if (u->source) {
600             if ((u->in_mmap = mmap(NULL, u->in_hwbuf_size, PROT_READ, MAP_SHARED, u->fd, 0)) == MAP_FAILED) {
601                 pa_log("Resume failed, mmap(): %s", pa_cstrerror(errno));
602                 goto fail;
603             }
604         }
605
606         if (u->sink) {
607             if ((u->out_mmap = mmap(NULL, u->out_hwbuf_size, PROT_WRITE, MAP_SHARED, u->fd, 0)) == MAP_FAILED) {
608                 pa_log("Resume failed, mmap(): %s", pa_cstrerror(errno));
609                 if (u->in_mmap && u->in_mmap != MAP_FAILED) {
610                     munmap(u->in_mmap, u->in_hwbuf_size);
611                     u->in_mmap = NULL;
612                 }
613
614                 goto fail;
615             }
616
617             pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss);
618         }
619     }
620
621     u->out_mmap_current = u->in_mmap_current = 0;
622     u->out_mmap_saved_nfrags = u->in_mmap_saved_nfrags = 0;
623
624     pa_assert(!u->rtpoll_item);
625
626     build_pollfd(u);
627
628     if (u->sink && u->sink->get_volume)
629         u->sink->get_volume(u->sink);
630     if (u->source && u->source->get_volume)
631         u->source->get_volume(u->source);
632
633     pa_log_info("Resumed successfully...");
634
635     return 0;
636
637 fail:
638     pa_close(u->fd);
639     u->fd = -1;
640     return -1;
641 }
642
643 /* Called from IO context */
644 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
645     struct userdata *u = PA_SINK(o)->userdata;
646     int ret;
647     pa_bool_t do_trigger = FALSE, quick = TRUE;
648
649     switch (code) {
650
651         case PA_SINK_MESSAGE_GET_LATENCY: {
652             pa_usec_t r = 0;
653
654             if (u->fd >= 0) {
655                 if (u->use_mmap)
656                     r = mmap_sink_get_latency(u);
657                 else
658                     r = io_sink_get_latency(u);
659             }
660
661             *((pa_usec_t*) data) = r;
662
663             return 0;
664         }
665
666         case PA_SINK_MESSAGE_SET_STATE:
667
668             switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
669
670                 case PA_SINK_SUSPENDED:
671                     pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
672
673                     if (!u->source || u->source_suspended) {
674                         if (suspend(u) < 0)
675                             return -1;
676                     }
677
678                     do_trigger = TRUE;
679
680                     u->sink_suspended = TRUE;
681                     break;
682
683                 case PA_SINK_IDLE:
684                 case PA_SINK_RUNNING:
685
686                     if (u->sink->thread_info.state == PA_SINK_INIT) {
687                         do_trigger = TRUE;
688                         quick = u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state);
689                     }
690
691                     if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
692
693                         if (!u->source || u->source_suspended) {
694                             if (unsuspend(u) < 0)
695                                 return -1;
696                             quick = FALSE;
697                         }
698
699                         do_trigger = TRUE;
700
701                         u->out_mmap_current = 0;
702                         u->out_mmap_saved_nfrags = 0;
703
704                         u->sink_suspended = FALSE;
705                     }
706
707                     break;
708
709                 case PA_SINK_INVALID_STATE:
710                 case PA_SINK_UNLINKED:
711                 case PA_SINK_INIT:
712                     ;
713             }
714
715             break;
716
717     }
718
719     ret = pa_sink_process_msg(o, code, data, offset, chunk);
720
721     if (do_trigger)
722         trigger(u, quick);
723
724     return ret;
725 }
726
727 static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
728     struct userdata *u = PA_SOURCE(o)->userdata;
729     int ret;
730     int do_trigger = FALSE, quick = TRUE;
731
732     switch (code) {
733
734         case PA_SOURCE_MESSAGE_GET_LATENCY: {
735             pa_usec_t r = 0;
736
737             if (u->fd >= 0) {
738                 if (u->use_mmap)
739                     r = mmap_source_get_latency(u);
740                 else
741                     r = io_source_get_latency(u);
742             }
743
744             *((pa_usec_t*) data) = r;
745             return 0;
746         }
747
748         case PA_SOURCE_MESSAGE_SET_STATE:
749
750             switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
751                 case PA_SOURCE_SUSPENDED:
752                     pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
753
754                     if (!u->sink || u->sink_suspended) {
755                         if (suspend(u) < 0)
756                             return -1;
757                     }
758
759                     do_trigger = TRUE;
760
761                     u->source_suspended = TRUE;
762                     break;
763
764                 case PA_SOURCE_IDLE:
765                 case PA_SOURCE_RUNNING:
766
767                     if (u->source->thread_info.state == PA_SOURCE_INIT) {
768                         do_trigger = TRUE;
769                         quick = u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state);
770                     }
771
772                     if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
773
774                         if (!u->sink || u->sink_suspended) {
775                             if (unsuspend(u) < 0)
776                                 return -1;
777                             quick = FALSE;
778                         }
779
780                         do_trigger = TRUE;
781
782                         u->in_mmap_current = 0;
783                         u->in_mmap_saved_nfrags = 0;
784
785                         u->source_suspended = FALSE;
786                     }
787                     break;
788
789                 case PA_SOURCE_UNLINKED:
790                 case PA_SOURCE_INIT:
791                 case PA_SOURCE_INVALID_STATE:
792                     ;
793
794             }
795             break;
796
797     }
798
799     ret = pa_source_process_msg(o, code, data, offset, chunk);
800
801     if (do_trigger)
802         trigger(u, quick);
803
804     return ret;
805 }
806
807 static void sink_get_volume(pa_sink *s) {
808     struct userdata *u;
809
810     pa_assert_se(u = s->userdata);
811
812     pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
813
814     if (u->mixer_devmask & SOUND_MASK_VOLUME)
815         if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_VOLUME, &s->sample_spec, &s->real_volume) >= 0)
816             return;
817
818     if (u->mixer_devmask & SOUND_MASK_PCM)
819         if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_PCM, &s->sample_spec, &s->real_volume) >= 0)
820             return;
821
822     pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
823 }
824
825 static void sink_set_volume(pa_sink *s) {
826     struct userdata *u;
827
828     pa_assert_se(u = s->userdata);
829
830     pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
831
832     if (u->mixer_devmask & SOUND_MASK_VOLUME)
833         if (pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_VOLUME, &s->sample_spec, &s->real_volume) >= 0)
834             return;
835
836     if (u->mixer_devmask & SOUND_MASK_PCM)
837         if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_PCM, &s->sample_spec, &s->real_volume) >= 0)
838             return;
839
840     pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
841 }
842
843 static void source_get_volume(pa_source *s) {
844     struct userdata *u;
845
846     pa_assert_se(u = s->userdata);
847
848     pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
849
850     if (u->mixer_devmask & SOUND_MASK_IGAIN)
851         if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_IGAIN, &s->sample_spec, &s->volume) >= 0)
852             return;
853
854     if (u->mixer_devmask & SOUND_MASK_RECLEV)
855         if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_RECLEV, &s->sample_spec, &s->volume) >= 0)
856             return;
857
858     pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
859 }
860
861 static void source_set_volume(pa_source *s) {
862     struct userdata *u;
863
864     pa_assert_se(u = s->userdata);
865
866     pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
867
868     if (u->mixer_devmask & SOUND_MASK_IGAIN)
869         if (pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_IGAIN, &s->sample_spec, &s->volume) >= 0)
870             return;
871
872     if (u->mixer_devmask & SOUND_MASK_RECLEV)
873         if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_RECLEV, &s->sample_spec, &s->volume) >= 0)
874             return;
875
876     pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
877 }
878
879 static void thread_func(void *userdata) {
880     struct userdata *u = userdata;
881     int write_type = 0, read_type = 0;
882     short revents = 0;
883
884     pa_assert(u);
885
886     pa_log_debug("Thread starting up");
887
888     if (u->core->realtime_scheduling)
889         pa_make_realtime(u->core->realtime_priority);
890
891     pa_thread_mq_install(&u->thread_mq);
892
893     for (;;) {
894         int ret;
895
896 /*        pa_log("loop");    */
897
898         if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state))
899             if (u->sink->thread_info.rewind_requested)
900                 pa_sink_process_rewind(u->sink, 0);
901
902         /* Render some data and write it to the dsp */
903
904         if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->use_mmap || u->use_getospace)) {
905
906             if (u->use_mmap) {
907
908                 if ((ret = mmap_write(u)) < 0)
909                     goto fail;
910
911                 revents &= ~POLLOUT;
912
913                 if (ret > 0)
914                     continue;
915
916             } else {
917                 ssize_t l;
918                 pa_bool_t loop = FALSE, work_done = FALSE;
919
920                 l = (ssize_t) u->out_fragment_size;
921
922                 if (u->use_getospace) {
923                     audio_buf_info info;
924
925                     if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
926                         pa_log_info("Device doesn't support SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno));
927                         u->use_getospace = FALSE;
928                     } else {
929                         l = info.bytes;
930
931                         /* We loop only if GETOSPACE worked and we
932                          * actually *know* that we can write more than
933                          * one fragment at a time */
934                         loop = TRUE;
935                     }
936                 }
937
938                 /* Round down to multiples of the fragment size,
939                  * because OSS needs that (at least some versions
940                  * do) */
941                 l = (l/(ssize_t) u->out_fragment_size) * (ssize_t) u->out_fragment_size;
942
943                 /* Hmm, so poll() signalled us that we can read
944                  * something, but GETOSPACE told us there was nothing?
945                  * Hmm, make the best of it, try to read some data, to
946                  * avoid spinning forever. */
947                 if (l <= 0 && (revents & POLLOUT)) {
948                     l = (ssize_t) u->out_fragment_size;
949                     loop = FALSE;
950                 }
951
952                 while (l > 0) {
953                     void *p;
954                     ssize_t t;
955
956                     if (u->memchunk.length <= 0)
957                         pa_sink_render(u->sink, (size_t) l, &u->memchunk);
958
959                     pa_assert(u->memchunk.length > 0);
960
961                     p = pa_memblock_acquire(u->memchunk.memblock);
962                     t = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type);
963                     pa_memblock_release(u->memchunk.memblock);
964
965 /*                     pa_log("wrote %i bytes of %u", t, l); */
966
967                     pa_assert(t != 0);
968
969                     if (t < 0) {
970
971                         if (errno == EINTR)
972                             continue;
973
974                         else if (errno == EAGAIN) {
975                             pa_log_debug("EAGAIN");
976
977                             revents &= ~POLLOUT;
978                             break;
979
980                         } else {
981                             pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno));
982                             goto fail;
983                         }
984
985                     } else {
986
987                         u->memchunk.index += (size_t) t;
988                         u->memchunk.length -= (size_t) t;
989
990                         if (u->memchunk.length <= 0) {
991                             pa_memblock_unref(u->memchunk.memblock);
992                             pa_memchunk_reset(&u->memchunk);
993                         }
994
995                         l -= t;
996
997                         revents &= ~POLLOUT;
998                         work_done = TRUE;
999                     }
1000
1001                     if (!loop)
1002                         break;
1003                 }
1004
1005                 if (work_done)
1006                     continue;
1007             }
1008         }
1009
1010         /* Try to read some data and pass it on to the source driver. */
1011
1012         if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state) && ((revents & POLLIN) || u->use_mmap || u->use_getispace)) {
1013
1014             if (u->use_mmap) {
1015
1016                 if ((ret = mmap_read(u)) < 0)
1017                     goto fail;
1018
1019                 revents &= ~POLLIN;
1020
1021                 if (ret > 0)
1022                     continue;
1023
1024             } else {
1025
1026                 void *p;
1027                 ssize_t l;
1028                 pa_memchunk memchunk;
1029                 pa_bool_t loop = FALSE, work_done = FALSE;
1030
1031                 l = (ssize_t) u->in_fragment_size;
1032
1033                 if (u->use_getispace) {
1034                     audio_buf_info info;
1035
1036                     if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
1037                         pa_log_info("Device doesn't support SNDCTL_DSP_GETISPACE: %s", pa_cstrerror(errno));
1038                         u->use_getispace = FALSE;
1039                     } else {
1040                         l = info.bytes;
1041                         loop = TRUE;
1042                     }
1043                 }
1044
1045                 l = (l/(ssize_t) u->in_fragment_size) * (ssize_t) u->in_fragment_size;
1046
1047                 if (l <= 0 && (revents & POLLIN)) {
1048                     l = (ssize_t) u->in_fragment_size;
1049                     loop = FALSE;
1050                 }
1051
1052                 while (l > 0) {
1053                     ssize_t t;
1054                     size_t k;
1055
1056                     pa_assert(l > 0);
1057
1058                     memchunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
1059
1060                     k = pa_memblock_get_length(memchunk.memblock);
1061
1062                     if (k > (size_t) l)
1063                         k = (size_t) l;
1064
1065                     k = (k/u->frame_size)*u->frame_size;
1066
1067                     p = pa_memblock_acquire(memchunk.memblock);
1068                     t = pa_read(u->fd, p, k, &read_type);
1069                     pa_memblock_release(memchunk.memblock);
1070
1071                     pa_assert(t != 0); /* EOF cannot happen */
1072
1073 /*                     pa_log("read %i bytes of %u", t, l); */
1074
1075                     if (t < 0) {
1076                         pa_memblock_unref(memchunk.memblock);
1077
1078                         if (errno == EINTR)
1079                             continue;
1080
1081                         else if (errno == EAGAIN) {
1082                             pa_log_debug("EAGAIN");
1083
1084                             revents &= ~POLLIN;
1085                             break;
1086
1087                         } else {
1088                             pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno));
1089                             goto fail;
1090                         }
1091
1092                     } else {
1093                         memchunk.index = 0;
1094                         memchunk.length = (size_t) t;
1095
1096                         pa_source_post(u->source, &memchunk);
1097                         pa_memblock_unref(memchunk.memblock);
1098
1099                         l -= t;
1100
1101                         revents &= ~POLLIN;
1102                         work_done = TRUE;
1103                     }
1104
1105                     if (!loop)
1106                         break;
1107                 }
1108
1109                 if (work_done)
1110                     continue;
1111             }
1112         }
1113
1114 /*         pa_log("loop2 revents=%i", revents); */
1115
1116         if (u->rtpoll_item) {
1117             struct pollfd *pollfd;
1118
1119             pa_assert(u->fd >= 0);
1120
1121             pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
1122             pollfd->events = (short)
1123                 (((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
1124                  ((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0));
1125         }
1126
1127         /* Hmm, nothing to do. Let's sleep */
1128         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
1129             goto fail;
1130
1131         if (ret == 0)
1132             goto finish;
1133
1134         if (u->rtpoll_item) {
1135             struct pollfd *pollfd;
1136
1137             pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
1138
1139             if (pollfd->revents & ~(POLLOUT|POLLIN)) {
1140                 pa_log("DSP shutdown.");
1141                 goto fail;
1142             }
1143
1144             revents = pollfd->revents;
1145         } else
1146             revents = 0;
1147     }
1148
1149 fail:
1150     /* If this was no regular exit from the loop we have to continue
1151      * processing messages until we received PA_MESSAGE_SHUTDOWN */
1152     pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
1153     pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
1154
1155 finish:
1156     pa_log_debug("Thread shutting down");
1157 }
1158
1159 int pa__init(pa_module*m) {
1160
1161     struct audio_buf_info info;
1162     struct userdata *u = NULL;
1163     const char *dev;
1164     int fd = -1;
1165     int nfrags, orig_frag_size, frag_size;
1166     int mode, caps;
1167     pa_bool_t record = TRUE, playback = TRUE, use_mmap = TRUE;
1168     pa_sample_spec ss;
1169     pa_channel_map map;
1170     pa_modargs *ma = NULL;
1171     char hwdesc[64];
1172     const char *name;
1173     pa_bool_t namereg_fail;
1174     pa_sink_new_data sink_new_data;
1175     pa_source_new_data source_new_data;
1176
1177     pa_assert(m);
1178
1179     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1180         pa_log("Failed to parse module arguments.");
1181         goto fail;
1182     }
1183
1184     if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
1185         pa_log("record= and playback= expect boolean argument.");
1186         goto fail;
1187     }
1188
1189     if (!playback && !record) {
1190         pa_log("Neither playback nor record enabled for device.");
1191         goto fail;
1192     }
1193
1194     mode = (playback && record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
1195
1196     ss = m->core->default_sample_spec;
1197     map = m->core->default_channel_map;
1198     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_OSS) < 0) {
1199         pa_log("Failed to parse sample specification or channel map");
1200         goto fail;
1201     }
1202
1203     nfrags = (int) m->core->default_n_fragments;
1204     frag_size = (int) pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss);
1205     if (frag_size <= 0)
1206         frag_size = (int) pa_frame_size(&ss);
1207
1208     if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
1209         pa_log("Failed to parse fragments arguments");
1210         goto fail;
1211     }
1212
1213     if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
1214         pa_log("Failed to parse mmap argument.");
1215         goto fail;
1216     }
1217
1218     if ((fd = pa_oss_open(dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0)
1219         goto fail;
1220
1221     if (use_mmap && (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER))) {
1222         pa_log_info("OSS device not mmap capable, falling back to UNIX read/write mode.");
1223         use_mmap = FALSE;
1224     }
1225
1226     if (use_mmap && mode == O_WRONLY) {
1227         pa_log_info("Device opened for playback only, cannot do memory mapping, falling back to UNIX write() mode.");
1228         use_mmap = FALSE;
1229     }
1230
1231     if (pa_oss_get_hw_description(dev, hwdesc, sizeof(hwdesc)) >= 0)
1232         pa_log_info("Hardware name is '%s'.", hwdesc);
1233     else
1234         hwdesc[0] = 0;
1235
1236     pa_log_info("Device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
1237
1238     orig_frag_size = frag_size;
1239     if (nfrags >= 2 && frag_size >= 1)
1240         if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0)
1241             goto fail;
1242
1243     if (pa_oss_auto_format(fd, &ss) < 0)
1244         goto fail;
1245
1246     if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) {
1247         pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
1248         goto fail;
1249     }
1250     pa_assert(frag_size > 0);
1251
1252     u = pa_xnew0(struct userdata, 1);
1253     u->core = m->core;
1254     u->module = m;
1255     m->userdata = u;
1256     u->fd = fd;
1257     u->mixer_fd = -1;
1258     u->mixer_devmask = 0;
1259     u->use_getospace = u->use_getispace = TRUE;
1260     u->use_getodelay = TRUE;
1261     u->mode = mode;
1262     u->frame_size = pa_frame_size(&ss);
1263     u->device_name = pa_xstrdup(dev);
1264     u->in_nfrags = u->out_nfrags = (uint32_t) (u->nfrags = nfrags);
1265     u->out_fragment_size = u->in_fragment_size = (uint32_t) (u->frag_size = frag_size);
1266     u->orig_frag_size = orig_frag_size;
1267     u->use_mmap = use_mmap;
1268     u->rtpoll = pa_rtpoll_new();
1269     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
1270     u->rtpoll_item = NULL;
1271     build_pollfd(u);
1272
1273     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
1274         pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
1275         u->in_fragment_size = (uint32_t) info.fragsize;
1276         u->in_nfrags = (uint32_t) info.fragstotal;
1277         u->use_getispace = TRUE;
1278     }
1279
1280     if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
1281         pa_log_info("Output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
1282         u->out_fragment_size = (uint32_t) info.fragsize;
1283         u->out_nfrags = (uint32_t) info.fragstotal;
1284         u->use_getospace = TRUE;
1285     }
1286
1287     u->in_hwbuf_size = u->in_nfrags * u->in_fragment_size;
1288     u->out_hwbuf_size = u->out_nfrags * u->out_fragment_size;
1289
1290     if (mode != O_WRONLY) {
1291         char *name_buf = NULL;
1292
1293         if (use_mmap) {
1294             if ((u->in_mmap = mmap(NULL, u->in_hwbuf_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
1295                 pa_log_warn("mmap(PROT_READ) failed, reverting to non-mmap mode: %s", pa_cstrerror(errno));
1296                 use_mmap = u->use_mmap = FALSE;
1297                 u->in_mmap = NULL;
1298             } else
1299                 pa_log_debug("Successfully mmap()ed input buffer.");
1300         }
1301
1302         if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
1303             namereg_fail = TRUE;
1304         else {
1305             name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(dev));
1306             namereg_fail = FALSE;
1307         }
1308
1309         pa_source_new_data_init(&source_new_data);
1310         source_new_data.driver = __FILE__;
1311         source_new_data.module = m;
1312         pa_source_new_data_set_name(&source_new_data, name);
1313         source_new_data.namereg_fail = namereg_fail;
1314         pa_source_new_data_set_sample_spec(&source_new_data, &ss);
1315         pa_source_new_data_set_channel_map(&source_new_data, &map);
1316         pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_STRING, dev);
1317         pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_API, "oss");
1318         pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, hwdesc[0] ? hwdesc : dev);
1319         pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, use_mmap ? "mmap" : "serial");
1320         pa_proplist_setf(source_new_data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (u->in_hwbuf_size));
1321         pa_proplist_setf(source_new_data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (u->in_fragment_size));
1322
1323         if (pa_modargs_get_proplist(ma, "source_properties", source_new_data.proplist, PA_UPDATE_REPLACE) < 0) {
1324             pa_log("Invalid properties");
1325             pa_source_new_data_done(&source_new_data);
1326             goto fail;
1327         }
1328
1329         u->source = pa_source_new(m->core, &source_new_data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
1330         pa_source_new_data_done(&source_new_data);
1331         pa_xfree(name_buf);
1332
1333         if (!u->source) {
1334             pa_log("Failed to create source object");
1335             goto fail;
1336         }
1337
1338         u->source->parent.process_msg = source_process_msg;
1339         u->source->userdata = u;
1340
1341         pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
1342         pa_source_set_rtpoll(u->source, u->rtpoll);
1343         pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->in_hwbuf_size, &u->source->sample_spec));
1344         u->source->refresh_volume = TRUE;
1345
1346         if (use_mmap)
1347             u->in_mmap_memblocks = pa_xnew0(pa_memblock*, u->in_nfrags);
1348     }
1349
1350     if (mode != O_RDONLY) {
1351         char *name_buf = NULL;
1352
1353         if (use_mmap) {
1354             if ((u->out_mmap = mmap(NULL, u->out_hwbuf_size, PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
1355                 if (mode == O_RDWR) {
1356                     pa_log_debug("mmap() failed for input. Changing to O_WRONLY mode.");
1357                     mode = O_WRONLY;
1358                     goto go_on;
1359                 } else {
1360                     pa_log_warn("mmap(PROT_WRITE) failed, reverting to non-mmap mode: %s", pa_cstrerror(errno));
1361                     u->use_mmap = use_mmap = FALSE;
1362                     u->out_mmap = NULL;
1363                 }
1364             } else {
1365                 pa_log_debug("Successfully mmap()ed output buffer.");
1366                 pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss);
1367             }
1368         }
1369
1370         if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
1371             namereg_fail = TRUE;
1372         else {
1373             name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(dev));
1374             namereg_fail = FALSE;
1375         }
1376
1377         pa_sink_new_data_init(&sink_new_data);
1378         sink_new_data.driver = __FILE__;
1379         sink_new_data.module = m;
1380         pa_sink_new_data_set_name(&sink_new_data, name);
1381         sink_new_data.namereg_fail = namereg_fail;
1382         pa_sink_new_data_set_sample_spec(&sink_new_data, &ss);
1383         pa_sink_new_data_set_channel_map(&sink_new_data, &map);
1384         pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_STRING, dev);
1385         pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_API, "oss");
1386         pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, hwdesc[0] ? hwdesc : dev);
1387         pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, use_mmap ? "mmap" : "serial");
1388         pa_proplist_setf(sink_new_data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (u->out_hwbuf_size));
1389         pa_proplist_setf(sink_new_data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (u->out_fragment_size));
1390
1391         if (pa_modargs_get_proplist(ma, "sink_properties", sink_new_data.proplist, PA_UPDATE_REPLACE) < 0) {
1392             pa_log("Invalid properties");
1393             pa_sink_new_data_done(&sink_new_data);
1394             goto fail;
1395         }
1396
1397         u->sink = pa_sink_new(m->core, &sink_new_data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
1398         pa_sink_new_data_done(&sink_new_data);
1399         pa_xfree(name_buf);
1400
1401         if (!u->sink) {
1402             pa_log("Failed to create sink object");
1403             goto fail;
1404         }
1405
1406         u->sink->parent.process_msg = sink_process_msg;
1407         u->sink->userdata = u;
1408
1409         pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
1410         pa_sink_set_rtpoll(u->sink, u->rtpoll);
1411         pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->out_hwbuf_size, &u->sink->sample_spec));
1412         u->sink->refresh_volume = TRUE;
1413
1414         pa_sink_set_max_request(u->sink, u->out_hwbuf_size);
1415
1416         if (use_mmap)
1417             u->out_mmap_memblocks = pa_xnew0(pa_memblock*, u->out_nfrags);
1418     }
1419
1420     if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name)) >= 0) {
1421         pa_bool_t do_close = TRUE;
1422
1423         if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
1424             pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno));
1425
1426         else {
1427             if (u->sink && (u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM))) {
1428                 pa_log_debug("Found hardware mixer track for playback.");
1429                 u->sink->flags |= PA_SINK_HW_VOLUME_CTRL;
1430                 u->sink->get_volume = sink_get_volume;
1431                 u->sink->set_volume = sink_set_volume;
1432                 u->sink->n_volume_steps = 101;
1433                 do_close = FALSE;
1434             }
1435
1436             if (u->source && (u->mixer_devmask & (SOUND_MASK_RECLEV|SOUND_MASK_IGAIN))) {
1437                 pa_log_debug("Found hardware mixer track for recording.");
1438                 u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
1439                 u->source->get_volume = source_get_volume;
1440                 u->source->set_volume = source_set_volume;
1441                 u->source->n_volume_steps = 101;
1442                 do_close = FALSE;
1443             }
1444         }
1445
1446         if (do_close) {
1447             pa_close(u->mixer_fd);
1448             u->mixer_fd = -1;
1449             u->mixer_devmask = 0;
1450         }
1451     }
1452
1453 go_on:
1454
1455     pa_assert(u->source || u->sink);
1456
1457     pa_memchunk_reset(&u->memchunk);
1458
1459     if (!(u->thread = pa_thread_new(thread_func, u))) {
1460         pa_log("Failed to create thread.");
1461         goto fail;
1462     }
1463
1464     /* Read mixer settings */
1465     if (u->sink) {
1466         if (sink_new_data.volume_is_set) {
1467             if (u->sink->set_volume)
1468                 u->sink->set_volume(u->sink);
1469         } else {
1470             if (u->sink->get_volume)
1471                 u->sink->get_volume(u->sink);
1472         }
1473     }
1474
1475     if (u->source) {
1476         if (source_new_data.volume_is_set) {
1477             if (u->source->set_volume)
1478                 u->source->set_volume(u->source);
1479         } else {
1480             if (u->source->get_volume)
1481                 u->source->get_volume(u->source);
1482         }
1483     }
1484
1485     if (u->sink)
1486         pa_sink_put(u->sink);
1487     if (u->source)
1488         pa_source_put(u->source);
1489
1490     pa_modargs_free(ma);
1491
1492     return 0;
1493
1494 fail:
1495
1496     if (u)
1497         pa__done(m);
1498     else if (fd >= 0)
1499         pa_close(fd);
1500
1501     if (ma)
1502         pa_modargs_free(ma);
1503
1504     return -1;
1505 }
1506
1507 void pa__done(pa_module*m) {
1508     struct userdata *u;
1509
1510     pa_assert(m);
1511
1512     if (!(u = m->userdata))
1513         return;
1514
1515     if (u->sink)
1516         pa_sink_unlink(u->sink);
1517
1518     if (u->source)
1519         pa_source_unlink(u->source);
1520
1521     if (u->thread) {
1522         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
1523         pa_thread_free(u->thread);
1524     }
1525
1526     pa_thread_mq_done(&u->thread_mq);
1527
1528     if (u->sink)
1529         pa_sink_unref(u->sink);
1530
1531     if (u->source)
1532         pa_source_unref(u->source);
1533
1534     if (u->memchunk.memblock)
1535         pa_memblock_unref(u->memchunk.memblock);
1536
1537     if (u->rtpoll_item)
1538         pa_rtpoll_item_free(u->rtpoll_item);
1539
1540     if (u->rtpoll)
1541         pa_rtpoll_free(u->rtpoll);
1542
1543     if (u->out_mmap_memblocks) {
1544         unsigned i;
1545         for (i = 0; i < u->out_nfrags; i++)
1546             if (u->out_mmap_memblocks[i])
1547                 pa_memblock_unref_fixed(u->out_mmap_memblocks[i]);
1548         pa_xfree(u->out_mmap_memblocks);
1549     }
1550
1551     if (u->in_mmap_memblocks) {
1552         unsigned i;
1553         for (i = 0; i < u->in_nfrags; i++)
1554             if (u->in_mmap_memblocks[i])
1555                 pa_memblock_unref_fixed(u->in_mmap_memblocks[i]);
1556         pa_xfree(u->in_mmap_memblocks);
1557     }
1558
1559     if (u->in_mmap && u->in_mmap != MAP_FAILED)
1560         munmap(u->in_mmap, u->in_hwbuf_size);
1561
1562     if (u->out_mmap && u->out_mmap != MAP_FAILED)
1563         munmap(u->out_mmap, u->out_hwbuf_size);
1564
1565     if (u->fd >= 0)
1566         pa_close(u->fd);
1567
1568     if (u->mixer_fd >= 0)
1569         pa_close(u->mixer_fd);
1570
1571     pa_xfree(u->device_name);
1572
1573     pa_xfree(u);
1574 }