Avoid dynamic handling of libsndio
[openal-soft/openal-hmr.git] / Alc / backends / sndio.c
blob1d1c512c280625d937dd80fb85df47c484fcd9cf
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 static ALCboolean sndio_load(void)
38 return ALC_TRUE;
42 typedef struct {
43 struct sio_hdl *sndHandle;
45 ALvoid *mix_data;
46 ALsizei data_size;
48 volatile int killNow;
49 ALvoid *thread;
50 } sndio_data;
53 static ALuint sndio_proc(ALvoid *ptr)
55 ALCdevice *device = ptr;
56 sndio_data *data = device->ExtraData;
57 ALsizei frameSize;
58 size_t wrote;
60 SetRTPriority();
62 frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
64 while(!data->killNow && device->Connected)
66 ALsizei len = data->data_size;
67 ALubyte *WritePtr = data->mix_data;
69 aluMixData(device, WritePtr, len/frameSize);
70 while(len > 0 && !data->killNow)
72 wrote = sio_write(data->sndHandle, WritePtr, len);
73 if(wrote == 0)
75 ERR("sio_write failed\n");
76 aluHandleDisconnect(device);
77 break;
80 len -= wrote;
81 WritePtr += wrote;
85 return 0;
90 static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
92 sndio_data *data;
94 if(!deviceName)
95 deviceName = sndio_device;
96 else if(strcmp(deviceName, sndio_device) != 0)
97 return ALC_INVALID_VALUE;
99 data = calloc(1, sizeof(*data));
100 data->killNow = 0;
102 data->sndHandle = sio_open(NULL, SIO_PLAY, 0);
103 if(data->sndHandle == NULL)
105 free(data);
106 ERR("Could not open device\n");
107 return ALC_INVALID_VALUE;
110 device->DeviceName = strdup(deviceName);
111 device->ExtraData = data;
113 return ALC_NO_ERROR;
116 static void sndio_close_playback(ALCdevice *device)
118 sndio_data *data = device->ExtraData;
120 sio_close(data->sndHandle);
121 free(data);
122 device->ExtraData = NULL;
125 static ALCboolean sndio_reset_playback(ALCdevice *device)
127 sndio_data *data = device->ExtraData;
128 struct sio_par par;
130 sio_initpar(&par);
132 par.rate = device->Frequency;
133 par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
135 switch(device->FmtType)
137 case DevFmtByte:
138 par.bits = 8;
139 par.sig = 1;
140 break;
141 case DevFmtUByte:
142 par.bits = 8;
143 par.sig = 0;
144 break;
145 case DevFmtFloat:
146 case DevFmtShort:
147 par.bits = 16;
148 par.sig = 1;
149 break;
150 case DevFmtUShort:
151 par.bits = 16;
152 par.sig = 0;
153 break;
154 case DevFmtInt:
155 par.bits = 32;
156 par.sig = 1;
157 break;
158 case DevFmtUInt:
159 par.bits = 32;
160 par.sig = 0;
161 break;
163 par.le = SIO_LE_NATIVE;
165 par.round = device->UpdateSize;
166 par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
167 if(!par.appbufsz) par.appbufsz = device->UpdateSize;
169 if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par))
171 ERR("Failed to set device parameters\n");
172 return ALC_FALSE;
175 if(par.bits != par.bps*8)
177 ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
178 return ALC_FALSE;
181 device->Frequency = par.rate;
182 device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
184 if(par.bits == 8 && par.sig == 1)
185 device->FmtType = DevFmtByte;
186 else if(par.bits == 8 && par.sig == 0)
187 device->FmtType = DevFmtUByte;
188 else if(par.bits == 16 && par.sig == 1)
189 device->FmtType = DevFmtShort;
190 else if(par.bits == 16 && par.sig == 0)
191 device->FmtType = DevFmtUShort;
192 else if(par.bits == 32 && par.sig == 1)
193 device->FmtType = DevFmtInt;
194 else if(par.bits == 32 && par.sig == 0)
195 device->FmtType = DevFmtUInt;
196 else
198 ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
199 return ALC_FALSE;
202 device->UpdateSize = par.round;
203 device->NumUpdates = (par.bufsz/par.round) + 1;
205 SetDefaultChannelOrder(device);
207 return ALC_TRUE;
210 static ALCboolean sndio_start_playback(ALCdevice *device)
212 sndio_data *data = device->ExtraData;
214 if(!sio_start(data->sndHandle))
216 ERR("Error starting playback\n");
217 return ALC_FALSE;
220 data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
221 data->mix_data = calloc(1, data->data_size);
223 data->thread = StartThread(sndio_proc, device);
224 if(data->thread == NULL)
226 sio_stop(data->sndHandle);
227 free(data->mix_data);
228 data->mix_data = NULL;
229 return ALC_FALSE;
232 return ALC_TRUE;
235 static void sndio_stop_playback(ALCdevice *device)
237 sndio_data *data = device->ExtraData;
239 if(!data->thread)
240 return;
242 data->killNow = 1;
243 StopThread(data->thread);
244 data->thread = NULL;
246 data->killNow = 0;
247 if(!sio_stop(data->sndHandle))
248 ERR("Error stopping device\n");
250 free(data->mix_data);
251 data->mix_data = NULL;
255 static const BackendFuncs sndio_funcs = {
256 sndio_open_playback,
257 sndio_close_playback,
258 sndio_reset_playback,
259 sndio_start_playback,
260 sndio_stop_playback,
261 NULL,
262 NULL,
263 NULL,
264 NULL,
265 NULL,
266 NULL
269 ALCboolean alc_sndio_init(BackendFuncs *func_list)
271 if(!sndio_load())
272 return ALC_FALSE;
273 *func_list = sndio_funcs;
274 return ALC_TRUE;
277 void alc_sndio_deinit(void)
281 void alc_sndio_probe(enum DevProbe type)
283 switch(type)
285 case ALL_DEVICE_PROBE:
286 AppendAllDevicesList(sndio_device);
287 break;
288 case CAPTURE_DEVICE_PROBE:
289 break;