source: roaraudio/roard/driver_sndio.c @ 5278:b3e0dd3f3141

Last change on this file since 5278:b3e0dd3f3141 was 5278:b3e0dd3f3141, checked in by phi, 12 years ago

last parts of merging _nonblock into _ctl and fixed sizeof(cmd) of _ctls

File size: 7.0 KB
Line 
1//driver_sndio.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2011
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, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27#ifdef ROAR_HAVE_LIBSNDIO
28
29int driver_sndio_init_vio(struct roar_vio_calls * vio, struct driver_sndio * inst) {
30 if ( vio == NULL )
31  return -1;
32
33 memset(vio, 0, sizeof(struct roar_vio_calls));
34
35 vio->close    = driver_sndio_close_vio;
36 vio->write    = driver_sndio_write;
37 vio->sync     = driver_sndio_sync;
38 vio->ctl      = driver_sndio_ctl;
39
40 vio->inst     = (void*) inst;
41
42 return 0;
43}
44
45#define _err() if ( self->shandle != NULL ) sio_close(self->shandle);   \
46               if ( self->mhandle != NULL ) mio_close(self->mhandle);   \
47               if ( self->device  != NULL ) roar_mm_free(self->device); \
48               roar_mm_free(self);                              \
49               return -1
50
51int driver_sndio_open(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream) {
52 struct driver_sndio * self = NULL;
53
54 if ( (self = roar_mm_malloc(sizeof(struct driver_sndio))) == NULL ) {
55  ROAR_ERR("driver_sndio_open(*): Can not roar_mm_malloc() instance data: %s", strerror(errno));
56  return -1;
57 }
58
59 memset(self, 0, sizeof(struct driver_sndio));
60 memcpy(&(self->info), info, sizeof(struct roar_audio_info));
61
62 self->ssid = -1;
63
64 if ( sstream == NULL ) {
65  self->stream = NULL;
66  self->dir    = ROAR_DIR_OUTPUT;
67 } else {
68  self->stream = sstream;
69  self->dir    = ROAR_STREAM(sstream)->dir;
70
71  switch (self->dir) {
72   case ROAR_DIR_OUTPUT:
73   case ROAR_DIR_MONITOR:
74     self->dir = ROAR_DIR_OUTPUT;
75    break;
76   case ROAR_DIR_MIDI_OUT:
77     info->channels = 16;
78     info->codec    = ROAR_CODEC_MIDI;
79     info->bits     = 8;
80    break;
81   default:
82     _err();
83  }
84 }
85
86 if ( device != NULL )
87  self->device = roar_mm_strdup(device);
88
89 if ( driver_sndio_init_vio(inst, self) == -1 ) {
90  ROAR_ERR("driver_sndio_open(*): Can not init vio interface");
91  _err();
92 }
93
94 if ( driver_sndio_open_device(self) == -1 ) {
95  ROAR_ERR("driver_sndio_open(*): Can not open audio device");
96  _err();
97 }
98
99 ROAR_DBG("driver_sndio_open(*): sndio devices opened :)");
100
101 return 0;
102}
103#undef er
104
105int     driver_sndio_close_vio    (struct roar_vio_calls * vio) {
106 struct driver_sndio * self = vio->inst;
107
108 if ( self->shandle != NULL )
109  sio_close(self->shandle);
110
111 if ( self->mhandle != NULL )
112  mio_close(self->mhandle);
113
114 if ( self->device != NULL )
115  roar_mm_free(self->device);
116
117 roar_mm_free(self);
118
119 return 0;
120}
121
122int     driver_sndio_open_device  (struct driver_sndio * self) {
123
124 ROAR_DBG("driver_sndio_open_device(*) = ?");
125 switch (self->dir) {
126  case ROAR_DIR_OUTPUT:
127    if ( (self->shandle = sio_open(self->device, SIO_PLAY, 0)) == NULL ) {
128     ROAR_ERR("driver_sndio_open_device(*): Can not open sndio audio device");
129     return -1;
130    }
131   self->need_config = 1;
132   break;
133  case ROAR_DIR_MIDI_OUT:
134    if ( (self->mhandle = mio_open(self->device, MIO_OUT, 0)) == NULL ) {
135     ROAR_ERR("driver_sndio_open_device(*): Can not open sndio MIDI device");
136     return -1;
137    }
138   break;
139  default:
140    return -1;
141 }
142
143 ROAR_DBG("driver_sndio_open_device(*) = ?");
144 return 0;
145}
146
147int     driver_sndio_config_device(struct driver_sndio * self) {
148 struct sio_par par;
149
150 sio_initpar(&par);
151
152 par.bits  = self->info.bits;
153 par.rate  = self->info.rate;
154 par.pchan = self->info.channels;
155
156 switch (self->info.codec) {
157  case ROAR_CODEC_PCM_S_LE:
158    par.le  = 1;
159    par.sig = 1;
160   break;
161  case ROAR_CODEC_PCM_S_BE:
162    par.le  = 0;
163    par.sig = 1;
164   break;
165  case ROAR_CODEC_PCM_U_LE:
166    par.le  = 1;
167    par.sig = 0;
168   break;
169  case ROAR_CODEC_PCM_U_BE:
170    par.le  = 0;
171    par.sig = 0;
172   break;
173  default:
174    return -1;
175   break;
176 }
177
178 if ( sio_setpar(self->shandle, &par) == 0 ) {
179  ROAR_ERR("driver_sndio_config_device(*): Can not set stream parameters");
180  return -1;
181 }
182
183 if ( sio_start(self->shandle) == 0 ) {
184  ROAR_ERR("driver_sndio_config_device(*): Can not start stream");
185  return -1;
186 }
187
188 self->need_config = 0;
189
190 return 0;
191}
192
193int     driver_sndio_reopen_device(struct driver_sndio * self) {
194 return -1;
195}
196
197ssize_t driver_sndio_write        (struct roar_vio_calls * vio, void *buf, size_t count) {
198 struct driver_sndio * self = vio->inst;
199
200 ROAR_DBG("driver_sndio_write(*) = ?");
201
202 if ( self->need_config ) {
203  if ( driver_sndio_config_device(vio->inst) == -1 ) {
204   return -1;
205  }
206 }
207
208 ROAR_DBG("driver_sndio_write(*) = ?");
209
210 switch (self->dir) {
211  case ROAR_DIR_OUTPUT:
212    return sio_write(self->shandle, buf, count);
213   break;
214  case ROAR_DIR_MIDI_OUT:
215    return mio_write(self->mhandle, buf, count);
216   break;
217 }
218
219 ROAR_WARN("driver_sndio_write(*): Driver changed direction to something not supported, this should not happen");
220
221 return -1;
222}
223
224int     driver_sndio_sync         (struct roar_vio_calls * vio) {
225 return -1;
226}
227
228#define data(x) x: if ( data == NULL ) return -1;
229#define no_data(x) x: if ( data != NULL ) return -1;
230
231int     driver_sndio_ctl          (struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
232 struct driver_sndio * self = vio->inst;
233 unsigned d;
234
235 switch (cmd) {
236  case data(ROAR_VIO_CTL_SET_SSTREAMID)
237    self->ssid = *(int *)data;
238   break;
239  case data(ROAR_VIO_CTL_SET_SSTREAM)
240    // FIXME: we should do some better error handling here:
241    if ( ROAR_STREAM(data)->dir != self->dir ) return -1;
242    self->stream = data;
243   break;
244  case data(ROAR_VIO_CTL_GET_AUINFO)
245    memcpy(data, &(self->info), sizeof(struct roar_audio_info));
246   break;
247  case data(ROAR_VIO_CTL_SET_AUINFO)
248    memcpy(&(self->info), data, sizeof(struct roar_audio_info));
249    return driver_sndio_reopen_device(self);
250   break;
251  case ROAR_VIO_CTL_SET_VOLUME:
252    switch (self->info.channels) {
253     case 1:
254       d = ROAR_MIXER(data)->mixer[0] * SIO_MAXVOL / ROAR_MIXER(data)->scale;
255      break;
256     case 2:
257       if ( ROAR_MIXER(data)->mixer[0] != ROAR_MIXER(data)->mixer[1] )
258        return -1;
259       d = ROAR_MIXER(data)->mixer[0] * SIO_MAXVOL / ROAR_MIXER(data)->scale;
260      break;
261     default:
262      return -1;
263    }
264    return sio_setvol(self->shandle, d) == 0 ? -1 : 0;
265   break;
266  case ROAR_VIO_CTL_NONBLOCK:
267    if ( *(int*)data == ROAR_SOCKET_BLOCK )
268     return 0;
269    roar_err_set(ROAR_ERROR_NOTSUP);
270    return -1;
271   break;
272  default:
273    return -1;
274   break;
275 }
276
277 return 0;
278}
279
280#endif
281
282//ll
Note: See TracBrowser for help on using the repository browser.