Fix typo
[openal-soft/openal-hmr.git] / Alc / backends / sndio.c
blobfc36895152b9156b7b4386f110907369fd1b7a46
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "alMain.h"
27 #include "AL/al.h"
28 #include "AL/alc.h"
30 #include <sndio.h>
33 static const ALCchar sndio_device[] = "SndIO Default";
36 #ifdef HAVE_DYNLOAD
37 static void *sndio_handle;
38 #define MAKE_FUNC(x) static typeof(x) * p##x
39 MAKE_FUNC(sio_initpar);
40 MAKE_FUNC(sio_open);
41 MAKE_FUNC(sio_close);
42 MAKE_FUNC(sio_setpar);
43 MAKE_FUNC(sio_getpar);
44 MAKE_FUNC(sio_getcap);
45 MAKE_FUNC(sio_onmove);
46 MAKE_FUNC(sio_write);
47 MAKE_FUNC(sio_read);
48 MAKE_FUNC(sio_start);
49 MAKE_FUNC(sio_stop);
50 MAKE_FUNC(sio_nfds);
51 MAKE_FUNC(sio_pollfd);
52 MAKE_FUNC(sio_revents);
53 MAKE_FUNC(sio_eof);
54 MAKE_FUNC(sio_setvol);
55 MAKE_FUNC(sio_onvol);
57 #define sio_initpar psio_initpar
58 #define sio_open psio_open
59 #define sio_close psio_close
60 #define sio_setpar psio_setpar
61 #define sio_getpar psio_getpar
62 #define sio_getcap psio_getcap
63 #define sio_onmove psio_onmove
64 #define sio_write psio_write
65 #define sio_read psio_read
66 #define sio_start psio_start
67 #define sio_stop psio_stop
68 #define sio_nfds psio_nfds
69 #define sio_pollfd psio_pollfd
70 #define sio_revents psio_revents
71 #define sio_eof psio_eof
72 #define sio_setvol psio_setvol
73 #define sio_onvol psio_onvol
74 #endif
77 static ALCboolean sndio_load(void)
79 #ifdef HAVE_DYNLOAD
80 if(!sndio_handle)
82 sndio_handle = LoadLib("libsndio.so");
83 if(!sndio_handle)
84 return ALC_FALSE;
86 #define LOAD_FUNC(f) do { \
87 p##f = GetSymbol(sndio_handle, #f); \
88 if(p##f == NULL) { \
89 CloseLib(sndio_handle); \
90 sndio_handle = NULL; \
91 return ALC_FALSE; \
92 } \
93 } while(0)
94 LOAD_FUNC(sio_initpar);
95 LOAD_FUNC(sio_open);
96 LOAD_FUNC(sio_close);
97 LOAD_FUNC(sio_setpar);
98 LOAD_FUNC(sio_getpar);
99 LOAD_FUNC(sio_getcap);
100 LOAD_FUNC(sio_onmove);
101 LOAD_FUNC(sio_write);
102 LOAD_FUNC(sio_read);
103 LOAD_FUNC(sio_start);
104 LOAD_FUNC(sio_stop);
105 LOAD_FUNC(sio_nfds);
106 LOAD_FUNC(sio_pollfd);
107 LOAD_FUNC(sio_revents);
108 LOAD_FUNC(sio_eof);
109 LOAD_FUNC(sio_setvol);
110 LOAD_FUNC(sio_onvol);
111 #undef LOAD_FUNC
113 #endif
114 return ALC_TRUE;
118 typedef struct {
119 struct sio_hdl *sndHandle;
121 ALvoid *mix_data;
122 ALsizei data_size;
124 volatile int killNow;
125 ALvoid *thread;
126 } sndio_data;
129 static ALuint sndio_proc(ALvoid *ptr)
131 ALCdevice *device = ptr;
132 sndio_data *data = device->ExtraData;
133 ALsizei frameSize;
134 size_t wrote;
136 SetRTPriority();
138 frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
140 while(!data->killNow && device->Connected)
142 ALsizei len = data->data_size;
143 ALubyte *WritePtr = data->mix_data;
145 aluMixData(device, WritePtr, len/frameSize);
146 while(len > 0 && !data->killNow)
148 wrote = sio_write(data->sndHandle, WritePtr, len);
149 if(wrote == 0)
151 ERR("sio_write failed\n");
152 aluHandleDisconnect(device);
153 break;
156 len -= wrote;
157 WritePtr += wrote;
161 return 0;
166 static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
168 sndio_data *data;
170 if(!deviceName)
171 deviceName = sndio_device;
172 else if(strcmp(deviceName, sndio_device) != 0)
173 return ALC_INVALID_VALUE;
175 data = calloc(1, sizeof(*data));
176 data->killNow = 0;
178 data->sndHandle = sio_open(NULL, SIO_PLAY, 0);
179 if(data->sndHandle == NULL)
181 free(data);
182 ERR("Could not open device\n");
183 return ALC_INVALID_VALUE;
186 device->szDeviceName = strdup(deviceName);
187 device->ExtraData = data;
189 return ALC_NO_ERROR;
192 static void sndio_close_playback(ALCdevice *device)
194 sndio_data *data = device->ExtraData;
196 sio_close(data->sndHandle);
197 free(data);
198 device->ExtraData = NULL;
201 static ALCboolean sndio_reset_playback(ALCdevice *device)
203 sndio_data *data = device->ExtraData;
204 struct sio_par par;
206 sio_initpar(&par);
208 par.rate = device->Frequency;
209 par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
211 switch(device->FmtType)
213 case DevFmtByte:
214 par.bits = 8;
215 par.sig = 1;
216 break;
217 case DevFmtUByte:
218 par.bits = 8;
219 par.sig = 0;
220 break;
221 case DevFmtFloat:
222 case DevFmtShort:
223 par.bits = 16;
224 par.sig = 1;
225 break;
226 case DevFmtUShort:
227 par.bits = 16;
228 par.sig = 0;
229 break;
230 case DevFmtInt:
231 par.bits = 32;
232 par.sig = 1;
233 break;
234 case DevFmtUInt:
235 par.bits = 32;
236 par.sig = 0;
237 break;
239 par.le = SIO_LE_NATIVE;
241 par.round = device->UpdateSize;
242 par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
243 if(!par.appbufsz) par.appbufsz = device->UpdateSize;
245 if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par))
247 ERR("Failed to set device parameters\n");
248 return ALC_FALSE;
251 if(par.bits != par.bps*8)
253 ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
254 return ALC_FALSE;
257 device->Frequency = par.rate;
258 device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
260 if(par.bits == 8 && par.sig == 1)
261 device->FmtType = DevFmtByte;
262 else if(par.bits == 8 && par.sig == 0)
263 device->FmtType = DevFmtUByte;
264 else if(par.bits == 16 && par.sig == 1)
265 device->FmtType = DevFmtShort;
266 else if(par.bits == 16 && par.sig == 0)
267 device->FmtType = DevFmtUShort;
268 else if(par.bits == 32 && par.sig == 1)
269 device->FmtType = DevFmtInt;
270 else if(par.bits == 32 && par.sig == 0)
271 device->FmtType = DevFmtUInt;
272 else
274 ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
275 return ALC_FALSE;
278 device->UpdateSize = par.round;
279 device->NumUpdates = (par.bufsz/par.round) + 1;
281 SetDefaultChannelOrder(device);
283 return ALC_TRUE;
286 static ALCboolean sndio_start_playback(ALCdevice *device)
288 sndio_data *data = device->ExtraData;
290 if(!sio_start(data->sndHandle))
292 ERR("Error starting playback\n");
293 return ALC_FALSE;
296 data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
297 data->mix_data = calloc(1, data->data_size);
299 data->thread = StartThread(sndio_proc, device);
300 if(data->thread == NULL)
302 sio_stop(data->sndHandle);
303 free(data->mix_data);
304 data->mix_data = NULL;
305 return ALC_FALSE;
308 return ALC_TRUE;
311 static void sndio_stop_playback(ALCdevice *device)
313 sndio_data *data = device->ExtraData;
315 if(!data->thread)
316 return;
318 data->killNow = 1;
319 StopThread(data->thread);
320 data->thread = NULL;
322 data->killNow = 0;
323 if(!sio_stop(data->sndHandle))
324 ERR("Error stopping device\n");
326 free(data->mix_data);
327 data->mix_data = NULL;
331 static const BackendFuncs sndio_funcs = {
332 sndio_open_playback,
333 sndio_close_playback,
334 sndio_reset_playback,
335 sndio_start_playback,
336 sndio_stop_playback,
337 NULL,
338 NULL,
339 NULL,
340 NULL,
341 NULL,
342 NULL
345 ALCboolean alc_sndio_init(BackendFuncs *func_list)
347 if(!sndio_load())
348 return ALC_FALSE;
349 *func_list = sndio_funcs;
350 return ALC_TRUE;
353 void alc_sndio_deinit(void)
355 #ifdef HAVE_DYNLOAD
356 if(sndio_handle)
357 CloseLib(sndio_handle);
358 sndio_handle = NULL;
359 #endif
362 void alc_sndio_probe(enum DevProbe type)
364 switch(type)
366 case ALL_DEVICE_PROBE:
367 AppendAllDeviceList(sndio_device);
368 break;
369 case CAPTURE_DEVICE_PROBE:
370 break;