source: roaraudio/roard/driver_sndio.c @ 5012:b263759832f1

Last change on this file since 5012:b263759832f1 was 5012:b263759832f1, checked in by phi, 13 years ago

Updated drivers to use new sync stream selection logic correctly (Closes: #136)

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