source: roaraudio/roard/driver_oss.c @ 1209:731db415c4df

Last change on this file since 1209:731db415c4df was 1209:731db415c4df, checked in by phi, 15 years ago

reduced the OSS fragment (buffer) size, latenys of 35ms!

File size: 6.0 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
35#ifdef ROAR_DEFAULT_OSS_DEV
36 if ( device == NULL )
37  device = ROAR_DEFAULT_OSS_DEV;
38#endif
39
40 if ( device == NULL ) {
41  ROAR_ERR("driver_oss_open(*): no default device found, you need to specify one manuelly");
42  return -1;
43 }
44
45 roar_vio_init_calls(inst);
46 inst->sync = driver_oss_sync;
47 inst->ctl  = driver_oss_ctl;
48
49 if (  fh == -1 ) {
50  if ( (fh = open(device, O_WRONLY, 0644)) == -1 ) {
51   ROAR_ERR("driver_oss_open(*): Can not open OSS device: %s: %s", device, strerror(errno));
52   return -1;
53  }
54 }
55
56 roar_vio_set_fh(inst, fh);
57
58
59
60#ifdef SNDCTL_DSP_CHANNELS
61 tmp = info->channels;
62
63 if ( ioctl(fh, SNDCTL_DSP_CHANNELS, &tmp) == -1 ) {
64  ROAR_ERR("driver_oss_open(*): can not set number of channels");
65  er();
66 }
67
68 if ( tmp != info->channels ) {
69   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);
70  er();
71 }
72#else
73 switch (info->channels) {
74  case  1: tmp = 0; break;
75  case  2: tmp = 1; break;
76  default: er();
77 }
78
79 if ( ioctl(fh, SNDCTL_DSP_STEREO, &tmp) == -1 ) {
80  ROAR_ERR("driver_oss_open(*): can not set number of channels");
81  er();
82 }
83#endif
84
85 switch (info->codec) {
86  case ROAR_CODEC_PCM_S_LE:
87    switch (info->bits) {
88     case  8: tmp = AFMT_S8;     break;
89     case 16: tmp = AFMT_S16_LE; break;
90//     case 24: tmp = AFMT_S24_PACKED; break;
91#ifdef AFMT_S32_LE
92     case 32: tmp = AFMT_S32_LE; break;
93#endif
94     default: er();
95    }
96   break;
97  case ROAR_CODEC_PCM_S_BE:
98    switch (info->bits) {
99     case  8: tmp = AFMT_S8;     break;
100     case 16: tmp = AFMT_S16_BE; break;
101//     case 24: tmp = AFMT_S24_PACKED; break;
102#ifdef AFMT_S32_BE
103     case 32: tmp = AFMT_S32_BE; break;
104#endif
105     default: er();
106    }
107   break;
108  case ROAR_CODEC_PCM_U_LE:
109    switch (info->bits) {
110     case  8: tmp = AFMT_U8;     break;
111     case 16: tmp = AFMT_U16_LE; break;
112     default: er();
113    }
114   break;
115  case ROAR_CODEC_PCM_U_BE:
116    switch (info->bits) {
117     case  8: tmp = AFMT_U8;     break;
118     case 16: tmp = AFMT_U16_BE; break;
119     default: er();
120    }
121  case ROAR_CODEC_ALAW:
122    tmp = AFMT_A_LAW;
123   break;
124  case ROAR_CODEC_MULAW:
125    tmp = AFMT_MU_LAW;
126   break;
127#ifdef AFMT_VORBIS
128  case ROAR_CODEC_OGG_VORBIS:
129    tmp = AFMT_VORBIS;
130   break;
131#endif
132  default:
133    er();
134   break;
135 }
136
137 ctmp = tmp;
138#ifdef SNDCTL_DSP_SETFMT
139 if ( ioctl(fh, SNDCTL_DSP_SETFMT, &tmp) == -1 ) {
140#else
141 if ( ioctl(fh, SNDCTL_DSP_SAMPLESIZE, &tmp) == -1 ) {
142#endif
143  ROAR_ERR("driver_oss_open(*): can not set sample format");
144  er();
145 }
146
147 if ( tmp != ctmp ) {
148  es = NULL;
149  switch (tmp) {
150   case AFMT_S8    : es = "bits=8,codec=pcm";       break;
151   case AFMT_U8    : es = "bits=8,codec=pcm_u_le";  break;
152   case AFMT_S16_LE: es = "bits=16,codec=pcm_s_le"; break;
153   case AFMT_S16_BE: es = "bits=16,codec=pcm_s_be"; break;
154   case AFMT_U16_LE: es = "bits=16,codec=pcm_u_le"; break;
155   case AFMT_U16_BE: es = "bits=16,codec=pcm_u_be"; break;
156#ifdef AFMT_S32_LE
157   case AFMT_S32_LE: es = "bits=32,codec=pcm_s_le"; break;
158#endif
159#ifdef AFMT_S32_BE
160   case AFMT_S32_BE: es = "bits=32,codec=pcm_s_be"; break;
161#endif
162   case AFMT_A_LAW : es = "codec=alaw";             break;
163   case AFMT_MU_LAW: es = "codec=mulaw";            break;
164#ifdef AFMT_VORBIS
165   case AFMT_VORBIS: es = "codec=ogg_vorbis";       break;
166#endif
167  }
168
169  if ( es != NULL ) {
170   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);
171  } else {
172   ROAR_ERR("driver_oss_open(*): can not set requested codec, set codec manuelly via -oO codec=somecodec");
173  }
174  er();
175 }
176
177 tmp = info->rate;
178
179 if ( ioctl(fh, SNDCTL_DSP_SPEED, &tmp) == -1 ) {
180  ROAR_ERR("driver_oss_open(*): can not set sample rate");
181  er();
182 }
183
184 if ( tmp < info->rate * 0.98 || tmp > info->rate * 1.02 ) {
185  ROAR_ERR("driver_oss_open(*): sample rate out of acceptable accuracy");
186  er();
187 }
188
189
190#ifdef SNDCTL_DSP_SETFRAGMENT
191 tmp = 4 << 16 | 11; // 4 fragements of 2048 Bytes.
192 if ( ioctl(fh, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1 ) {
193  ROAR_WARN("driver_oss_open(*): Can not set fragment size, sorry :(");
194 }
195#endif
196
197 ROAR_DBG("driver_oss_open(*): OSS devices opened :)");
198
199 return 0;
200}
201
202int driver_oss_close(DRIVER_USERDATA_T   inst) {
203 return close(roar_vio_get_fh((struct roar_vio_calls *)inst));
204}
205
206int driver_oss_sync(struct roar_vio_calls * vio) {
207#ifdef SNDCTL_DSP_SYNC
208 return ioctl(roar_vio_get_fh(vio), SNDCTL_DSP_SYNC, NULL);
209#else
210 return 0;
211#endif
212}
213
214int driver_oss_ctl(struct roar_vio_calls * vio, int cmd, void * data) {
215#ifdef SNDCTL_DSP_GETODELAY
216 int d;
217
218 if ( vio == NULL )
219  return -1;
220
221 if ( cmd != ROAR_VIO_CTL_GET_DELAY )
222  return -1;
223
224 if ( ioctl(roar_vio_get_fh(vio), SNDCTL_DSP_GETODELAY, &d) == -1 )
225  return -1;
226
227 ROAR_DBG("driver_oss_ctl(*): delay=%i byte", d);
228
229 *(uint_least32_t *)data = d;
230
231 return 0;
232#else
233 return -1;
234#endif
235}
236
237#endif
238//ll
Note: See TracBrowser for help on using the repository browser.