zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
sndio.c
Go to the documentation of this file.
1 
21 #include "config.h"
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "alMain.h"
28 #include "alu.h"
29 
30 #include <sndio.h>
31 
32 
33 static const ALCchar sndio_device[] = "SndIO Default";
34 
35 
36 static ALCboolean sndio_load(void)
37 {
38  return ALC_TRUE;
39 }
40 
41 
42 typedef struct {
43  struct sio_hdl *sndHandle;
44 
45  ALvoid *mix_data;
46  ALsizei data_size;
47 
48  volatile int killNow;
49  ALvoid *thread;
50 } sndio_data;
51 
52 
53 static ALuint sndio_proc(ALvoid *ptr)
54 {
55  ALCdevice *device = ptr;
56  sndio_data *data = device->ExtraData;
57  ALsizei frameSize;
58  size_t wrote;
59 
60  SetRTPriority();
61 
62  frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
63 
64  while(!data->killNow && device->Connected)
65  {
66  ALsizei len = data->data_size;
67  ALubyte *WritePtr = data->mix_data;
68 
69  aluMixData(device, WritePtr, len/frameSize);
70  while(len > 0 && !data->killNow)
71  {
72  wrote = sio_write(data->sndHandle, WritePtr, len);
73  if(wrote == 0)
74  {
75  ERR("sio_write failed\n");
76  ALCdevice_Lock(device);
77  aluHandleDisconnect(device);
78  ALCdevice_Unlock(device);
79  break;
80  }
81 
82  len -= wrote;
83  WritePtr += wrote;
84  }
85  }
86 
87  return 0;
88 }
89 
90 
91 
92 static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
93 {
94  sndio_data *data;
95 
96  if(!deviceName)
97  deviceName = sndio_device;
98  else if(strcmp(deviceName, sndio_device) != 0)
99  return ALC_INVALID_VALUE;
100 
101  data = calloc(1, sizeof(*data));
102  data->killNow = 0;
103 
104  data->sndHandle = sio_open(NULL, SIO_PLAY, 0);
105  if(data->sndHandle == NULL)
106  {
107  free(data);
108  ERR("Could not open device\n");
109  return ALC_INVALID_VALUE;
110  }
111 
112  device->DeviceName = strdup(deviceName);
113  device->ExtraData = data;
114 
115  return ALC_NO_ERROR;
116 }
117 
118 static void sndio_close_playback(ALCdevice *device)
119 {
120  sndio_data *data = device->ExtraData;
121 
122  sio_close(data->sndHandle);
123  free(data);
124  device->ExtraData = NULL;
125 }
126 
128 {
129  sndio_data *data = device->ExtraData;
130  struct sio_par par;
131 
132  sio_initpar(&par);
133 
134  par.rate = device->Frequency;
135  par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
136 
137  switch(device->FmtType)
138  {
139  case DevFmtByte:
140  par.bits = 8;
141  par.sig = 1;
142  break;
143  case DevFmtUByte:
144  par.bits = 8;
145  par.sig = 0;
146  break;
147  case DevFmtFloat:
148  case DevFmtShort:
149  par.bits = 16;
150  par.sig = 1;
151  break;
152  case DevFmtUShort:
153  par.bits = 16;
154  par.sig = 0;
155  break;
156  case DevFmtInt:
157  par.bits = 32;
158  par.sig = 1;
159  break;
160  case DevFmtUInt:
161  par.bits = 32;
162  par.sig = 0;
163  break;
164  }
165  par.le = SIO_LE_NATIVE;
166 
167  par.round = device->UpdateSize;
168  par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
169  if(!par.appbufsz) par.appbufsz = device->UpdateSize;
170 
171  if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par))
172  {
173  ERR("Failed to set device parameters\n");
174  return ALC_FALSE;
175  }
176 
177  if(par.bits != par.bps*8)
178  {
179  ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
180  return ALC_FALSE;
181  }
182 
183  device->Frequency = par.rate;
184  device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
185 
186  if(par.bits == 8 && par.sig == 1)
187  device->FmtType = DevFmtByte;
188  else if(par.bits == 8 && par.sig == 0)
189  device->FmtType = DevFmtUByte;
190  else if(par.bits == 16 && par.sig == 1)
191  device->FmtType = DevFmtShort;
192  else if(par.bits == 16 && par.sig == 0)
193  device->FmtType = DevFmtUShort;
194  else if(par.bits == 32 && par.sig == 1)
195  device->FmtType = DevFmtInt;
196  else if(par.bits == 32 && par.sig == 0)
197  device->FmtType = DevFmtUInt;
198  else
199  {
200  ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
201  return ALC_FALSE;
202  }
203 
204  device->UpdateSize = par.round;
205  device->NumUpdates = (par.bufsz/par.round) + 1;
206 
207  SetDefaultChannelOrder(device);
208 
209  return ALC_TRUE;
210 }
211 
213 {
214  sndio_data *data = device->ExtraData;
215 
216  if(!sio_start(data->sndHandle))
217  {
218  ERR("Error starting playback\n");
219  return ALC_FALSE;
220  }
221 
222  data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
223  data->mix_data = calloc(1, data->data_size);
224 
225  data->thread = StartThread(sndio_proc, device);
226  if(data->thread == NULL)
227  {
228  sio_stop(data->sndHandle);
229  free(data->mix_data);
230  data->mix_data = NULL;
231  return ALC_FALSE;
232  }
233 
234  return ALC_TRUE;
235 }
236 
237 static void sndio_stop_playback(ALCdevice *device)
238 {
239  sndio_data *data = device->ExtraData;
240 
241  if(!data->thread)
242  return;
243 
244  data->killNow = 1;
245  StopThread(data->thread);
246  data->thread = NULL;
247 
248  data->killNow = 0;
249  if(!sio_stop(data->sndHandle))
250  ERR("Error stopping device\n");
251 
252  free(data->mix_data);
253  data->mix_data = NULL;
254 }
255 
256 
257 static const BackendFuncs sndio_funcs = {
263  NULL,
264  NULL,
265  NULL,
266  NULL,
267  NULL,
268  NULL,
272 };
273 
275 {
276  if(!sndio_load())
277  return ALC_FALSE;
278  *func_list = sndio_funcs;
279  return ALC_TRUE;
280 }
281 
283 {
284 }
285 
287 {
288  switch(type)
289  {
290  case ALL_DEVICE_PROBE:
292  break;
294  break;
295  }
296 }
unsigned char ALubyte
Definition: al.h:47
ALCboolean Connected
Definition: alMain.h:564
void ALvoid
Definition: al.h:74
#define ALC_TRUE
Definition: alc.h:84
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
static const ALCchar sndio_device[]
Definition: sndio.c:33
char * strdup(const char *inStr)
Definition: strdup.c:6
#define NULL
Definition: ftobjs.h:61
static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
Definition: sndio.c:92
int ALsizei
Definition: al.h:62
SDL_EventEntry * free
Definition: SDL_events.c:80
ALuint Frequency
Definition: alMain.h:569
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
Definition: ALu.c:970
static ALCboolean sndio_start_playback(ALCdevice *device)
Definition: sndio.c:212
ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device)
Definition: ALc.c:1285
GLenum GLsizei len
Definition: glew.h:7035
void SetDefaultChannelOrder(ALCdevice *device)
Definition: ALc.c:1352
#define calloc
Definition: SDL_malloc.c:636
static ALuint sndio_proc(ALvoid *ptr)
Definition: sndio.c:53
ALvoid aluHandleDisconnect(ALCdevice *device)
Definition: ALu.c:1176
char ALCchar
Definition: alc.h:42
#define ALCdevice_Unlock(a)
Definition: alMain.h:647
void * ExtraData
Definition: alMain.h:630
#define ALC_FALSE
Definition: alc.h:81
static void sndio_close_playback(ALCdevice *device)
Definition: sndio.c:118
ALuint StopThread(ALvoid *thread)
Definition: alcThread.c:131
static ALCboolean sndio_reset_playback(ALCdevice *device)
Definition: sndio.c:127
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
static ALCboolean sndio_load(void)
Definition: sndio.c:36
void alc_sndio_probe(enum DevProbe type)
Definition: sndio.c:286
unsigned int ALuint
Definition: al.h:59
void SetRTPriority(void)
Definition: helpers.c:470
enum DevFmtChannels FmtChans
Definition: alMain.h:572
static void sndio_stop_playback(ALCdevice *device)
Definition: sndio.c:237
ALCboolean alc_sndio_init(BackendFuncs *func_list)
Definition: sndio.c:274
static SDL_Thread * thread
static const BackendFuncs sndio_funcs
Definition: sndio.c:257
#define ALC_NO_ERROR
Definition: alc.h:102
void ALCdevice_LockDefault(ALCdevice *device)
Definition: ALc.c:1277
char ALCboolean
Definition: alc.h:39
void alc_sndio_deinit(void)
Definition: sndio.c:282
#define ERR(...)
Definition: alMain.h:816
ALuint UpdateSize
Definition: alMain.h:570
ALuint NumUpdates
Definition: alMain.h:571
enum DevFmtType FmtType
Definition: alMain.h:573
ALCchar * DeviceName
Definition: alMain.h:575
#define ALC_INVALID_VALUE
Definition: alc.h:114
int ALCenum
Definition: alc.h:66
void ALCdevice_UnlockDefault(ALCdevice *device)
Definition: ALc.c:1281
#define ALCdevice_Lock(a)
Definition: alMain.h:646
void AppendAllDevicesList(const ALCchar *name)
ALvoid * StartThread(ALuint(*func)(ALvoid *), ALvoid *ptr)
Definition: alcThread.c:100
DevProbe
Definition: alMain.h:383
static __inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type)
Definition: alMain.h:523