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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 static const ALCchar sndio_device
[] = "SndIO Default";
37 static ALCboolean
sndio_load(void)
44 struct sio_hdl
*sndHandle
;
54 static int sndio_proc(void *ptr
)
56 ALCdevice
*device
= ptr
;
57 sndio_data
*data
= device
->ExtraData
;
62 althrd_setname(althrd_current(), MIXER_THREAD_NAME
);
64 frameSize
= FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
);
66 while(!data
->killNow
&& device
->Connected
)
68 ALsizei len
= data
->data_size
;
69 ALubyte
*WritePtr
= data
->mix_data
;
71 aluMixData(device
, WritePtr
, len
/frameSize
);
72 while(len
> 0 && !data
->killNow
)
74 wrote
= sio_write(data
->sndHandle
, WritePtr
, len
);
77 ERR("sio_write failed\n");
78 ALCdevice_Lock(device
);
79 aluHandleDisconnect(device
);
80 ALCdevice_Unlock(device
);
94 static ALCenum
sndio_open_playback(ALCdevice
*device
, const ALCchar
*deviceName
)
99 deviceName
= sndio_device
;
100 else if(strcmp(deviceName
, sndio_device
) != 0)
101 return ALC_INVALID_VALUE
;
103 data
= calloc(1, sizeof(*data
));
106 data
->sndHandle
= sio_open(NULL
, SIO_PLAY
, 0);
107 if(data
->sndHandle
== NULL
)
110 ERR("Could not open device\n");
111 return ALC_INVALID_VALUE
;
114 al_string_copy_cstr(&device
->DeviceName
, deviceName
);
115 device
->ExtraData
= data
;
120 static void sndio_close_playback(ALCdevice
*device
)
122 sndio_data
*data
= device
->ExtraData
;
124 sio_close(data
->sndHandle
);
126 device
->ExtraData
= NULL
;
129 static ALCboolean
sndio_reset_playback(ALCdevice
*device
)
131 sndio_data
*data
= device
->ExtraData
;
136 par
.rate
= device
->Frequency
;
137 par
.pchan
= ((device
->FmtChans
!= DevFmtMono
) ? 2 : 1);
139 switch(device
->FmtType
)
167 par
.le
= SIO_LE_NATIVE
;
169 par
.round
= device
->UpdateSize
;
170 par
.appbufsz
= device
->UpdateSize
* (device
->NumUpdates
-1);
171 if(!par
.appbufsz
) par
.appbufsz
= device
->UpdateSize
;
173 if(!sio_setpar(data
->sndHandle
, &par
) || !sio_getpar(data
->sndHandle
, &par
))
175 ERR("Failed to set device parameters\n");
179 if(par
.bits
!= par
.bps
*8)
181 ERR("Padded samples not supported (%u of %u bits)\n", par
.bits
, par
.bps
*8);
185 device
->Frequency
= par
.rate
;
186 device
->FmtChans
= ((par
.pchan
==1) ? DevFmtMono
: DevFmtStereo
);
188 if(par
.bits
== 8 && par
.sig
== 1)
189 device
->FmtType
= DevFmtByte
;
190 else if(par
.bits
== 8 && par
.sig
== 0)
191 device
->FmtType
= DevFmtUByte
;
192 else if(par
.bits
== 16 && par
.sig
== 1)
193 device
->FmtType
= DevFmtShort
;
194 else if(par
.bits
== 16 && par
.sig
== 0)
195 device
->FmtType
= DevFmtUShort
;
196 else if(par
.bits
== 32 && par
.sig
== 1)
197 device
->FmtType
= DevFmtInt
;
198 else if(par
.bits
== 32 && par
.sig
== 0)
199 device
->FmtType
= DevFmtUInt
;
202 ERR("Unhandled sample format: %s %u-bit\n", (par
.sig
?"signed":"unsigned"), par
.bits
);
206 device
->UpdateSize
= par
.round
;
207 device
->NumUpdates
= (par
.bufsz
/par
.round
) + 1;
209 SetDefaultChannelOrder(device
);
214 static ALCboolean
sndio_start_playback(ALCdevice
*device
)
216 sndio_data
*data
= device
->ExtraData
;
218 if(!sio_start(data
->sndHandle
))
220 ERR("Error starting playback\n");
224 data
->data_size
= device
->UpdateSize
* FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
);
225 data
->mix_data
= calloc(1, data
->data_size
);
228 if(althrd_create(&data
->thread
, sndio_proc
, device
) != althrd_success
)
230 sio_stop(data
->sndHandle
);
231 free(data
->mix_data
);
232 data
->mix_data
= NULL
;
239 static void sndio_stop_playback(ALCdevice
*device
)
241 sndio_data
*data
= device
->ExtraData
;
248 althrd_join(data
->thread
, &res
);
250 if(!sio_stop(data
->sndHandle
))
251 ERR("Error stopping device\n");
253 free(data
->mix_data
);
254 data
->mix_data
= NULL
;
258 static const BackendFuncs sndio_funcs
= {
260 sndio_close_playback
,
261 sndio_reset_playback
,
262 sndio_start_playback
,
272 ALCboolean
alc_sndio_init(BackendFuncs
*func_list
)
276 *func_list
= sndio_funcs
;
280 void alc_sndio_deinit(void)
284 void alc_sndio_probe(enum DevProbe type
)
288 case ALL_DEVICE_PROBE
:
289 AppendAllDevicesList(sndio_device
);
291 case CAPTURE_DEVICE_PROBE
: