VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/ossaudio.c@ 61

Last change on this file since 61 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.7 KB
Line 
1/*
2 * QEMU OSS audio driver
3 *
4 * Copyright (c) 2003-2005 Vassili Karpov (malc)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include <fcntl.h>
25#include <errno.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <sys/mman.h>
29#include <sys/types.h>
30#include <sys/ioctl.h>
31#include <sys/soundcard.h>
32
33#include "Builtins.h"
34#include "../../vl_vbox.h"
35#include "audio.h"
36#include <iprt/alloc.h>
37
38#define AUDIO_CAP "oss"
39#include "audio_int.h"
40
41typedef struct OSSVoiceOut {
42 HWVoiceOut hw;
43 void *pcm_buf;
44 int fd;
45 int nfrags;
46 int fragsize;
47#ifndef __L4ENV__
48 int mmapped;
49#endif
50 int old_optr;
51} OSSVoiceOut;
52
53typedef struct OSSVoiceIn {
54 HWVoiceIn hw;
55 void *pcm_buf;
56 int fd;
57 int nfrags;
58 int fragsize;
59 int old_optr;
60} OSSVoiceIn;
61
62static struct {
63#ifndef __L4ENV__
64 int try_mmap;
65#endif
66 int nfrags;
67 int fragsize;
68 const char *devpath_out;
69 const char *devpath_in;
70 int debug;
71} conf = {
72#ifndef __L4ENV__
73 INIT_FIELD (try_mmap =) 0,
74#endif
75 INIT_FIELD (nfrags =) 4,
76 INIT_FIELD (fragsize =) 4096,
77 INIT_FIELD (devpath_out =) "/dev/dsp",
78 INIT_FIELD (devpath_in =) "/dev/dsp",
79 INIT_FIELD (debug =) 0,
80};
81
82struct oss_params {
83 int freq;
84 audfmt_e fmt;
85 int nchannels;
86 int nfrags;
87 int fragsize;
88};
89
90static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
91{
92 va_list ap;
93
94 va_start (ap, fmt);
95 AUD_vlog (AUDIO_CAP, fmt, ap);
96 va_end (ap);
97
98 AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
99}
100
101static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
102 int err,
103 const char *typ,
104 const char *fmt,
105 ...
106 )
107{
108 va_list ap;
109
110 AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
111
112 va_start (ap, fmt);
113 AUD_vlog (AUDIO_CAP, fmt, ap);
114 va_end (ap);
115
116 AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
117}
118
119static void oss_anal_close (int *fdp)
120{
121 int err = close (*fdp);
122 if (err) {
123 oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp);
124 }
125 *fdp = -1;
126}
127
128static int oss_write (SWVoiceOut *sw, void *buf, int len)
129{
130 return audio_pcm_sw_write (sw, buf, len);
131}
132
133static int aud_to_ossfmt (audfmt_e fmt)
134{
135 switch (fmt) {
136 case AUD_FMT_S8:
137 return AFMT_S8;
138
139 case AUD_FMT_U8:
140 return AFMT_U8;
141
142 case AUD_FMT_S16:
143 return AFMT_S16_LE;
144
145 case AUD_FMT_U16:
146 return AFMT_U16_LE;
147
148 default:
149 dolog ("Internal logic error: Bad audio format %d\n", fmt);
150#ifdef DEBUG_AUDIO
151 abort ();
152#endif
153 return AFMT_U8;
154 }
155}
156
157static int oss_to_audfmt (int ossfmt, audfmt_e *fmt, int *endianness)
158{
159 switch (ossfmt) {
160 case AFMT_S8:
161 *endianness = 0;
162 *fmt = AUD_FMT_S8;
163 break;
164
165 case AFMT_U8:
166 *endianness = 0;
167 *fmt = AUD_FMT_U8;
168 break;
169
170 case AFMT_S16_LE:
171 *endianness = 0;
172 *fmt = AUD_FMT_S16;
173 break;
174
175 case AFMT_U16_LE:
176 *endianness = 0;
177 *fmt = AUD_FMT_U16;
178 break;
179
180 case AFMT_S16_BE:
181 *endianness = 1;
182 *fmt = AUD_FMT_S16;
183 break;
184
185 case AFMT_U16_BE:
186 *endianness = 1;
187 *fmt = AUD_FMT_U16;
188 break;
189
190 default:
191 dolog ("Unrecognized audio format %d\n", ossfmt);
192 return -1;
193 }
194
195 return 0;
196}
197
198#if defined DEBUG_MISMATCHES || defined DEBUG
199static void oss_dump_info (struct oss_params *req, struct oss_params *obt)
200{
201 dolog ("parameter | requested value | obtained value\n");
202 dolog ("format | %10d | %10d\n", req->fmt, obt->fmt);
203 dolog ("channels | %10d | %10d\n",
204 req->nchannels, obt->nchannels);
205 dolog ("frequency | %10d | %10d\n", req->freq, obt->freq);
206 dolog ("nfrags | %10d | %10d\n", req->nfrags, obt->nfrags);
207 dolog ("fragsize | %10d | %10d\n",
208 req->fragsize, obt->fragsize);
209}
210#endif
211
212static int oss_open (int in, struct oss_params *req,
213 struct oss_params *obt, int *pfd)
214{
215 int fd;
216 int mmmmssss;
217 audio_buf_info abinfo;
218 int fmt, freq, nchannels;
219 const char *dspname = in ? conf.devpath_in : conf.devpath_out;
220 const char *typ = in ? "ADC" : "DAC";
221
222 fd = open (dspname, (in ? O_RDONLY : O_WRONLY) | O_NONBLOCK);
223 if (-1 == fd) {
224 oss_logerr2 (errno, typ, "Failed to open `%s'\n", dspname);
225 LogRel(("Audio/OSS: Failed to open '%s' as %s\n", dspname, typ));
226 return -1;
227 }
228
229 freq = req->freq;
230 nchannels = req->nchannels;
231 fmt = req->fmt;
232
233 if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
234 oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt);
235 goto err;
236 }
237
238 if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
239 oss_logerr2 (errno, typ, "Failed to set number of channels %d\n",
240 req->nchannels);
241 goto err;
242 }
243
244 if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
245 oss_logerr2 (errno, typ, "Failed to set frequency %d\n", req->freq);
246 goto err;
247 }
248
249 if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
250 oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
251 goto err;
252 }
253
254 mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
255 if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
256 oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n",
257 req->nfrags, req->fragsize);
258 goto err;
259 }
260
261 if (ioctl (fd, in ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) {
262 oss_logerr2 (errno, typ, "Failed to get buffer length\n");
263 goto err;
264 }
265
266 obt->fmt = fmt;
267 obt->nchannels = nchannels;
268 obt->freq = freq;
269 obt->nfrags = abinfo.fragstotal;
270 obt->fragsize = abinfo.fragsize;
271 *pfd = fd;
272
273#ifdef DEBUG_MISMATCHES
274 if ((req->fmt != obt->fmt) ||
275 (req->nchannels != obt->nchannels) ||
276 (req->freq != obt->freq) ||
277 (req->fragsize != obt->fragsize) ||
278 (req->nfrags != obt->nfrags)) {
279 dolog ("Audio parameters mismatch\n");
280 oss_dump_info (req, obt);
281 }
282#endif
283
284#ifdef DEBUG
285 oss_dump_info (req, obt);
286#endif
287 return 0;
288
289 err:
290 oss_anal_close (&fd);
291 return -1;
292}
293
294static int oss_run_out (HWVoiceOut *hw)
295{
296 OSSVoiceOut *oss = (OSSVoiceOut *) hw;
297 int err, rpos, live, decr;
298 int samples;
299 uint8_t *dst;
300 st_sample_t *src;
301 struct audio_buf_info abinfo;
302 struct count_info cntinfo;
303 int bufsize;
304
305 live = audio_pcm_hw_get_live_out (hw);
306 if (!live) {
307 return 0;
308 }
309
310 bufsize = hw->samples << hw->info.shift;
311
312#ifndef __L4ENV__
313 if (oss->mmapped) {
314 int bytes;
315
316 err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
317 if (err < 0) {
318 oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
319 return 0;
320 }
321
322 if (cntinfo.ptr == oss->old_optr) {
323 if (abs (hw->samples - live) < 64) {
324 dolog ("warning: Overrun\n");
325 }
326 return 0;
327 }
328
329 if (cntinfo.ptr > oss->old_optr) {
330 bytes = cntinfo.ptr - oss->old_optr;
331 }
332 else {
333 bytes = bufsize + cntinfo.ptr - oss->old_optr;
334 }
335
336 decr = audio_MIN (bytes >> hw->info.shift, live);
337 }
338 else {
339#endif
340 err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
341 if (err < 0) {
342 oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
343 return 0;
344 }
345
346 if (abinfo.bytes > bufsize) {
347 if (conf.debug) {
348 dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
349 "please report your OS/audio hw to malc@pulsesoft.com\n",
350 abinfo.bytes, bufsize);
351 }
352 abinfo.bytes = bufsize;
353 }
354
355 if (abinfo.bytes < 0) {
356 if (conf.debug) {
357 dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
358 abinfo.bytes, bufsize);
359 }
360 return 0;
361 }
362
363 decr = audio_MIN (abinfo.bytes >> hw->info.shift, live);
364 if (!decr) {
365 return 0;
366 }
367#ifndef __L4ENV__
368 }
369#endif
370
371 samples = decr;
372 rpos = hw->rpos;
373 while (samples) {
374 int left_till_end_samples = hw->samples - rpos;
375 int convert_samples = audio_MIN (samples, left_till_end_samples);
376
377 src = hw->mix_buf + rpos;
378 dst = advance (oss->pcm_buf, rpos << hw->info.shift);
379
380 hw->clip (dst, src, convert_samples);
381#ifdef __L4ENV__
382 {
383#else
384 if (!oss->mmapped) {
385#endif
386 int written;
387
388 written = write (oss->fd, dst, convert_samples << hw->info.shift);
389 /* XXX: follow errno recommendations ? */
390 if (written == -1) {
391 oss_logerr (
392 errno,
393 "Failed to write %d bytes of audio data from %p\n",
394 convert_samples << hw->info.shift,
395 dst
396 );
397 continue;
398 }
399
400 if (written != convert_samples << hw->info.shift) {
401 int wsamples = written >> hw->info.shift;
402 int wbytes = wsamples << hw->info.shift;
403 if (wbytes != written) {
404 dolog ("warning: Misaligned write %d (requested %d), "
405 "alignment %d\n",
406 wbytes, written, hw->info.align + 1);
407 }
408#if 0
409 mixeng_sniff_and_clear (hw, src, dst, wsamples);
410#endif
411 decr -= wsamples;
412 rpos = (rpos + wsamples) % hw->samples;
413 break;
414 }
415 }
416
417#if 0
418 mixeng_sniff_and_clear (hw, src, dst, convert_samples);
419#endif
420
421 rpos = (rpos + convert_samples) % hw->samples;
422 samples -= convert_samples;
423 }
424
425#ifndef __L4ENV__
426 if (oss->mmapped) {
427 oss->old_optr = cntinfo.ptr;
428 }
429#endif
430
431 hw->rpos = rpos;
432 return decr;
433}
434
435static void oss_fini_out (HWVoiceOut *hw)
436{
437 int err;
438 OSSVoiceOut *oss = (OSSVoiceOut *) hw;
439
440 ldebug ("oss_fini\n");
441 oss_anal_close (&oss->fd);
442
443 if (oss->pcm_buf) {
444#ifdef __L4ENV__
445 qemu_free (oss->pcm_buf);
446#else
447 if (oss->mmapped) {
448 err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
449 if (err) {
450 oss_logerr (errno, "Failed to unmap buffer %p, size %d\n",
451 oss->pcm_buf, hw->samples << hw->info.shift);
452 }
453 }
454 else {
455 qemu_free (oss->pcm_buf);
456 }
457#endif
458 oss->pcm_buf = NULL;
459 }
460}
461
462static int oss_init_out (HWVoiceOut *hw, audsettings_t *as)
463{
464 OSSVoiceOut *oss = (OSSVoiceOut *) hw;
465 struct oss_params req, obt;
466 int endianness;
467 int err;
468 int fd;
469 audfmt_e effective_fmt;
470 audsettings_t obt_as;
471
472 oss->fd = -1;
473
474 req.fmt = aud_to_ossfmt (as->fmt);
475 req.freq = as->freq;
476 req.nchannels = as->nchannels;
477 req.fragsize = conf.fragsize;
478 req.nfrags = conf.nfrags;
479
480 if (oss_open (0, &req, &obt, &fd)) {
481 return -1;
482 }
483
484 err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
485 if (err) {
486 oss_anal_close (&fd);
487 return -1;
488 }
489
490 obt_as.freq = obt.freq;
491 obt_as.nchannels = obt.nchannels;
492 obt_as.fmt = effective_fmt;
493 obt_as.endianness = endianness;
494
495 audio_pcm_init_info (&hw->info, &obt_as);
496 oss->nfrags = obt.nfrags;
497 oss->fragsize = obt.fragsize;
498
499 if (obt.nfrags * obt.fragsize & hw->info.align) {
500 dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n",
501 obt.nfrags * obt.fragsize, hw->info.align + 1);
502 }
503
504 hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
505
506#ifndef __L4ENV__
507 oss->mmapped = 0;
508 if (conf.try_mmap) {
509 oss->pcm_buf = mmap (
510 0,
511 hw->samples << hw->info.shift,
512 PROT_READ | PROT_WRITE,
513 MAP_SHARED,
514 fd,
515 0
516 );
517 if (oss->pcm_buf == MAP_FAILED) {
518 oss_logerr (errno, "Failed to map %d bytes of DAC\n",
519 hw->samples << hw->info.shift);
520 } else {
521 int err;
522 int trig = 0;
523 if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
524 oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
525 }
526 else {
527 trig = PCM_ENABLE_OUTPUT;
528 if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
529 oss_logerr (
530 errno,
531 "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
532 );
533 }
534 else {
535 oss->mmapped = 1;
536 }
537 }
538
539 if (!oss->mmapped) {
540 err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
541 if (err) {
542 oss_logerr (errno, "Failed to unmap buffer %p size %d\n",
543 oss->pcm_buf, hw->samples << hw->info.shift);
544 }
545 }
546 }
547 }
548#endif
549
550#ifndef __L4ENV__
551 if (!oss->mmapped) {
552#endif
553 oss->pcm_buf = audio_calloc (
554 AUDIO_FUNC,
555 hw->samples,
556 1 << hw->info.shift
557 );
558 if (!oss->pcm_buf) {
559 dolog (
560 "Could not allocate DAC buffer (%d samples, each %d bytes)\n",
561 hw->samples,
562 1 << hw->info.shift
563 );
564 oss_anal_close (&fd);
565 return -1;
566 }
567#ifndef __L4ENV__
568 }
569#endif
570
571 oss->fd = fd;
572 return 0;
573}
574
575static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
576{
577 int trig;
578 OSSVoiceOut *oss = (OSSVoiceOut *) hw;
579
580#ifdef __L4ENV__
581 return 0;
582#else
583 if (!oss->mmapped) {
584 return 0;
585 }
586#endif
587
588 switch (cmd) {
589 case VOICE_ENABLE:
590 ldebug ("enabling voice\n");
591 audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples);
592 trig = PCM_ENABLE_OUTPUT;
593 if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
594 oss_logerr (
595 errno,
596 "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
597 );
598 return -1;
599 }
600 break;
601
602 case VOICE_DISABLE:
603 ldebug ("disabling voice\n");
604 trig = 0;
605 if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
606 oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
607 return -1;
608 }
609 break;
610 }
611 return 0;
612}
613
614static int oss_init_in (HWVoiceIn *hw, audsettings_t *as)
615{
616 OSSVoiceIn *oss = (OSSVoiceIn *) hw;
617 struct oss_params req, obt;
618 int endianness;
619 int err;
620 int fd;
621 audfmt_e effective_fmt;
622 audsettings_t obt_as;
623
624 oss->fd = -1;
625
626 req.fmt = aud_to_ossfmt (as->fmt);
627 req.freq = as->freq;
628 req.nchannels = as->nchannels;
629 req.fragsize = conf.fragsize;
630 req.nfrags = conf.nfrags;
631 if (oss_open (1, &req, &obt, &fd)) {
632 return -1;
633 }
634
635 err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
636 if (err) {
637 oss_anal_close (&fd);
638 return -1;
639 }
640
641 obt_as.freq = obt.freq;
642 obt_as.nchannels = obt.nchannels;
643 obt_as.fmt = effective_fmt;
644 obt_as.endianness = endianness;
645
646 audio_pcm_init_info (&hw->info, &obt_as);
647 oss->nfrags = obt.nfrags;
648 oss->fragsize = obt.fragsize;
649
650 if (obt.nfrags * obt.fragsize & hw->info.align) {
651 dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n",
652 obt.nfrags * obt.fragsize, hw->info.align + 1);
653 }
654
655 hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
656 oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
657 if (!oss->pcm_buf) {
658 dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
659 hw->samples, 1 << hw->info.shift);
660 oss_anal_close (&fd);
661 return -1;
662 }
663
664 oss->fd = fd;
665 return 0;
666}
667
668static void oss_fini_in (HWVoiceIn *hw)
669{
670 OSSVoiceIn *oss = (OSSVoiceIn *) hw;
671
672 oss_anal_close (&oss->fd);
673
674 if (oss->pcm_buf) {
675 qemu_free (oss->pcm_buf);
676 oss->pcm_buf = NULL;
677 }
678}
679
680static int oss_run_in (HWVoiceIn *hw)
681{
682 OSSVoiceIn *oss = (OSSVoiceIn *) hw;
683 int hwshift = hw->info.shift;
684 int i;
685 int live = audio_pcm_hw_get_live_in (hw);
686 int dead = hw->samples - live;
687 size_t read_samples = 0;
688 struct {
689 int add;
690 int len;
691 } bufs[2];
692
693 bufs[0].add = hw->wpos;
694 bufs[0].len = 0;
695 bufs[1].add = 0;
696 bufs[1].len = 0;
697
698 if (!dead) {
699 return 0;
700 }
701
702 if (hw->wpos + dead > hw->samples) {
703 bufs[0].len = (hw->samples - hw->wpos) << hwshift;
704 bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift;
705 }
706 else {
707 bufs[0].len = dead << hwshift;
708 }
709
710
711 for (i = 0; i < 2; ++i) {
712 ssize_t nread;
713
714 if (bufs[i].len) {
715 void *p = advance (oss->pcm_buf, bufs[i].add << hwshift);
716 nread = read (oss->fd, p, bufs[i].len);
717
718 if (nread > 0) {
719 if (nread & hw->info.align) {
720 dolog ("warning: Misaligned read %"
721 FMTZ "d (requested %d), "
722 "alignment %d\n", nread, bufs[i].add << hwshift,
723 hw->info.align + 1);
724 }
725 read_samples += nread >> hwshift;
726 hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
727 &nominal_volume);
728 }
729
730 if (bufs[i].len - nread) {
731 if (nread == -1) {
732 switch (errno) {
733 case EINTR:
734 case EAGAIN:
735 break;
736 default:
737 oss_logerr (
738 errno,
739 "Failed to read %d bytes of audio (to %p)\n",
740 bufs[i].len, p
741 );
742 break;
743 }
744 }
745 break;
746 }
747 }
748 }
749
750 hw->wpos = (hw->wpos + read_samples) % hw->samples;
751 return read_samples;
752}
753
754static int oss_read (SWVoiceIn *sw, void *buf, int size)
755{
756 return audio_pcm_sw_read (sw, buf, size);
757}
758
759static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
760{
761 (void) hw;
762 (void) cmd;
763 return 0;
764}
765
766static void *oss_audio_init (void)
767{
768 return &conf;
769}
770
771static void oss_audio_fini (void *opaque)
772{
773 (void) opaque;
774}
775
776static struct audio_option oss_options[] = {
777 {"FRAGSIZE", AUD_OPT_INT, &conf.fragsize,
778 "Fragment size in bytes", NULL, 0},
779 {"NFRAGS", AUD_OPT_INT, &conf.nfrags,
780 "Number of fragments", NULL, 0},
781#ifndef __L4ENV__
782 {"MMAP", AUD_OPT_BOOL, &conf.try_mmap,
783 "Try using memory mapped access", NULL, 0},
784#endif
785 {"DAC_DEV", AUD_OPT_STR, &conf.devpath_out,
786 "Path to DAC device", NULL, 0},
787 {"ADC_DEV", AUD_OPT_STR, &conf.devpath_in,
788 "Path to ADC device", NULL, 0},
789 {"DEBUG", AUD_OPT_BOOL, &conf.debug,
790 "Turn on some debugging messages", NULL, 0},
791 {NULL, 0, NULL, NULL, NULL, 0}
792};
793
794static struct audio_pcm_ops oss_pcm_ops = {
795 oss_init_out,
796 oss_fini_out,
797 oss_run_out,
798 oss_write,
799 oss_ctl_out,
800
801 oss_init_in,
802 oss_fini_in,
803 oss_run_in,
804 oss_read,
805 oss_ctl_in
806};
807
808struct audio_driver oss_audio_driver = {
809 INIT_FIELD (name = ) "oss",
810 INIT_FIELD (descr = ) "OSS http://www.opensound.com",
811 INIT_FIELD (options = ) oss_options,
812 INIT_FIELD (init = ) oss_audio_init,
813 INIT_FIELD (fini = ) oss_audio_fini,
814 INIT_FIELD (pcm_ops = ) &oss_pcm_ops,
815 INIT_FIELD (can_be_default = ) 1,
816 INIT_FIELD (max_voices_out = ) INT_MAX,
817 INIT_FIELD (max_voices_in = ) INT_MAX,
818 INIT_FIELD (voice_size_out = ) sizeof (OSSVoiceOut),
819 INIT_FIELD (voice_size_in = ) sizeof (OSSVoiceIn)
820};
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette