source: roaraudio/roard/driver_oss.c @ 1242:86402240c209

Last change on this file since 1242:86402240c209 was 1242:86402240c209, checked in by phi, 15 years ago

use vio close

File size: 6.3 KB
Line 
1//driver_oss.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "roard.h"
26#if defined(ROAR_HAVE_OSS_BSD) || defined(ROAR_HAVE_OSS)
27
28#define er() close(fh); return -1
29
30int driver_oss_open(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh) {
31 int tmp;
32 int ctmp;
33 char * es;
34 uint32_t tmp32;
35
36#ifdef ROAR_DEFAULT_OSS_DEV
37 if ( device == NULL )
38  device = ROAR_DEFAULT_OSS_DEV;
39#endif
40
41 if ( device == NULL ) {
42  ROAR_ERR("driver_oss_open(*): no default device found, you need to specify one manuelly");
43  return -1;
44 }
45
46 roar_vio_init_calls(inst);
47 inst->sync = driver_oss_sync;
48 inst->ctl  = driver_oss_ctl;
49
50 if (  fh == -1 ) {
51  if ( (fh = open(device, O_WRONLY, 0644)) == -1 ) {
52   ROAR_ERR("driver_oss_open(*): Can not open OSS device: %s: %s", device, strerror(errno));
53   return -1;
54  }
55 }
56
57 roar_vio_set_fh(inst, fh);
58
59
60
61#ifdef SNDCTL_DSP_CHANNELS
62 tmp = info->channels;
63
64 if ( ioctl(fh, SNDCTL_DSP_CHANNELS, &tmp) == -1 ) {
65  ROAR_ERR("driver_oss_open(*): can not set number of channels");
66  er();
67 }
68
69 if ( tmp != info->channels ) {
70   ROAR_ERR("driver_oss_open(*): can not set requested numer of channels, OSS suggested %i channels, to use this restart with -oO channels=%i or set codec manuelly via -oO channels=num", tmp, tmp);
71  er();
72 }
73#else
74 switch (info->channels) {
75  case  1: tmp = 0; break;
76  case  2: tmp = 1; break;
77  default: er();
78 }
79
80 if ( ioctl(fh, SNDCTL_DSP_STEREO, &tmp) == -1 ) {
81  ROAR_ERR("driver_oss_open(*): can not set number of channels");
82  er();
83 }
84#endif
85
86 switch (info->codec) {
87  case ROAR_CODEC_PCM_S_LE:
88    switch (info->bits) {
89     case  8: tmp = AFMT_S8;     break;
90     case 16: tmp = AFMT_S16_LE; break;
91//     case 24: tmp = AFMT_S24_PACKED; break;
92#ifdef AFMT_S32_LE
93     case 32: tmp = AFMT_S32_LE; break;
94#endif
95     default: er();
96    }
97   break;
98  case ROAR_CODEC_PCM_S_BE:
99    switch (info->bits) {
100     case  8: tmp = AFMT_S8;     break;
101     case 16: tmp = AFMT_S16_BE; break;
102//     case 24: tmp = AFMT_S24_PACKED; break;
103#ifdef AFMT_S32_BE
104     case 32: tmp = AFMT_S32_BE; break;
105#endif
106     default: er();
107    }
108   break;
109  case ROAR_CODEC_PCM_U_LE:
110    switch (info->bits) {
111     case  8: tmp = AFMT_U8;     break;
112     case 16: tmp = AFMT_U16_LE; break;
113     default: er();
114    }
115   break;
116  case ROAR_CODEC_PCM_U_BE:
117    switch (info->bits) {
118     case  8: tmp = AFMT_U8;     break;
119     case 16: tmp = AFMT_U16_BE; break;
120     default: er();
121    }
122  case ROAR_CODEC_ALAW:
123    tmp = AFMT_A_LAW;
124   break;
125  case ROAR_CODEC_MULAW:
126    tmp = AFMT_MU_LAW;
127   break;
128#ifdef AFMT_VORBIS
129  case ROAR_CODEC_OGG_VORBIS:
130    tmp = AFMT_VORBIS;
131   break;
132#endif
133  default:
134    er();
135   break;
136 }
137
138 ctmp = tmp;
139#ifdef SNDCTL_DSP_SETFMT
140 if ( ioctl(fh, SNDCTL_DSP_SETFMT, &tmp) == -1 ) {
141#else
142 if ( ioctl(fh, SNDCTL_DSP_SAMPLESIZE, &tmp) == -1 ) {
143#endif
144  ROAR_ERR("driver_oss_open(*): can not set sample format");
145  er();
146 }
147
148 if ( tmp != ctmp ) {
149  es = NULL;
150  switch (tmp) {
151   case AFMT_S8    : es = "bits=8,codec=pcm";       break;
152   case AFMT_U8    : es = "bits=8,codec=pcm_u_le";  break;
153   case AFMT_S16_LE: es = "bits=16,codec=pcm_s_le"; break;
154   case AFMT_S16_BE: es = "bits=16,codec=pcm_s_be"; break;
155   case AFMT_U16_LE: es = "bits=16,codec=pcm_u_le"; break;
156   case AFMT_U16_BE: es = "bits=16,codec=pcm_u_be"; break;
157#ifdef AFMT_S32_LE
158   case AFMT_S32_LE: es = "bits=32,codec=pcm_s_le"; break;
159#endif
160#ifdef AFMT_S32_BE
161   case AFMT_S32_BE: es = "bits=32,codec=pcm_s_be"; break;
162#endif
163   case AFMT_A_LAW : es = "codec=alaw";             break;
164   case AFMT_MU_LAW: es = "codec=mulaw";            break;
165#ifdef AFMT_VORBIS
166   case AFMT_VORBIS: es = "codec=ogg_vorbis";       break;
167#endif
168  }
169
170  if ( es != NULL ) {
171   ROAR_ERR("driver_oss_open(*): can not set requested codec, OSS retruned another codec than requested, to use this restart with -oO %s or set codec manuelly via -oO codec=somecodec", es);
172  } else {
173   ROAR_ERR("driver_oss_open(*): can not set requested codec, set codec manuelly via -oO codec=somecodec");
174  }
175  er();
176 }
177
178 tmp = info->rate;
179
180 if ( ioctl(fh, SNDCTL_DSP_SPEED, &tmp) == -1 ) {
181  ROAR_ERR("driver_oss_open(*): can not set sample rate");
182  er();
183 }
184
185 if ( tmp < info->rate * 0.98 || tmp > info->rate * 1.02 ) {
186  ROAR_ERR("driver_oss_open(*): sample rate out of acceptable accuracy");
187  er();
188 }
189
190
191 tmp32 = 4;
192 driver_oss_ctl(inst, ROAR_VIO_CTL_SET_DBLOCKS, &tmp32);
193
194 ROAR_DBG("driver_oss_open(*): OSS devices opened :)");
195
196 return 0;
197}
198
199int driver_oss_close(DRIVER_USERDATA_T   inst) {
200 return roar_vio_close((struct roar_vio_calls *)inst);
201}
202
203int driver_oss_sync(struct roar_vio_calls * vio) {
204#ifdef SNDCTL_DSP_SYNC
205 return ioctl(roar_vio_get_fh(vio), SNDCTL_DSP_SYNC, NULL);
206#else
207 return 0;
208#endif
209}
210
211int driver_oss_ctl(struct roar_vio_calls * vio, int cmd, void * data) {
212 int d;
213
214 if ( vio == NULL )
215  return -1;
216
217 switch (cmd) {
218  case ROAR_VIO_CTL_GET_DELAY:
219#ifdef SNDCTL_DSP_GETODELAY
220    if ( ioctl(roar_vio_get_fh(vio), SNDCTL_DSP_GETODELAY, &d) == -1 )
221     return -1;
222
223    ROAR_DBG("driver_oss_ctl(*): delay=%i byte", d);
224
225    *(uint_least32_t *)data = d;
226#else
227    return -1;
228#endif
229   break;
230  case ROAR_VIO_CTL_SET_DBLOCKS:
231#ifdef SNDCTL_DSP_SETFRAGMENT
232    d = (*(uint_least32_t *)data) << 16 | 11; // (*data) fragements of 2048 Bytes.
233    if ( ioctl(roar_vio_get_fh(vio), SNDCTL_DSP_SETFRAGMENT, &d) == -1 ) {
234     ROAR_WARN("driver_oss_ctl(*): Can not set fragment size, sorry :(");
235    }
236#else
237    return -1;
238#endif
239   break;
240  case ROAR_VIO_CTL_GET_DBLKSIZE:
241    *(uint_least32_t *)data = 2048;
242    return 0;
243   break;
244  default:
245   return -1;
246 }
247
248 return 0;
249}
250
251#endif
252//ll
Note: See TracBrowser for help on using the repository browser.