1 #include <stdlib.h>
2 #include <string.h>
3 #include "sexyal.h"
4 #include "convert.h"
5 
6 
7 /* kludge.  yay. */
8 SexyAL_enumdevice *SexyALI_OSS_EnumerateDevices(void);
9 SexyAL_device *SexyALI_OSS_Open(char *id, SexyAL_format *format, SexyAL_buffering *buffering);
10 SexyAL_device *SexyALI_ESD_Open(char *id, SexyAL_format *format, SexyAL_buffering *buffering);
11 SexyAL_device *SexyALI_JACK_Open(char *id, SexyAL_format *format, SexyAL_buffering *buffering);
12 SexyAL_device *SexyALI_SDL_Open(char *id, SexyAL_format *format, SexyAL_buffering *buffering);
13 SexyAL_device *SexyALI_DSound_Open(char *id, SexyAL_format *format, SexyAL_buffering *buffering);
14 
FtoB(const SexyAL_format * format,uint32_t frames)15 static uint32_t FtoB(const SexyAL_format *format, uint32_t frames)
16 {
17  return(frames*format->channels*(format->sampformat>>4));
18 }
19 /*
20 static uint32_t BtoF(const SexyAL_format *format, uint32_t bytes)
21 {
22  return(bytes / (format->channels * (format->sampformat>>4)));
23 }
24 */
CanWrite(SexyAL_device * device)25 static uint32_t CanWrite(SexyAL_device *device)
26 {
27  uint32_t bytes,frames;
28 
29  bytes=device->RawCanWrite(device);
30  frames=bytes / device->format.channels / (device->format.sampformat>>4);
31 
32  return(frames);
33 }
34 
Write(SexyAL_device * device,void * data,uint32_t frames)35 static uint32_t Write(SexyAL_device *device, void *data, uint32_t frames)
36 {
37  uint8_t buffer[2048 * 4 * 2]; // Maximum frame size, 4 bytes * 2 channels
38  uint32_t frame_count = 0;
39 
40  while(frames)
41  {
42   int32_t tmp;
43   uint32_t fctmp;
44 
45   tmp=frames;
46   if(tmp>2048)
47   {
48    tmp=2048;
49    frames-=2048;
50   }
51   else frames-=tmp;
52 
53   SexiALI_Convert(&device->srcformat, &device->format, buffer, data, tmp);
54 
55   fctmp = device->RawWrite(device,buffer,FtoB(&device->format,tmp));
56   frame_count += fctmp;
57 
58   if(fctmp != tmp) /* Uh oh. */
59    return(frame_count);
60  }
61  return(frame_count);
62 }
63 
Close(SexyAL_device * device)64 static int Close(SexyAL_device *device)
65 {
66  return(device->RawClose(device));
67 }
68 
SetConvert(struct __SexyAL_device * device,SexyAL_format * format)69 int SetConvert(struct __SexyAL_device *device, SexyAL_format *format)
70 {
71  memcpy(&device->srcformat,format,sizeof(SexyAL_format));
72  return(1);
73 }
74 
Destroy(SexyAL * iface)75 void Destroy(SexyAL *iface)
76 {
77  free(iface);
78 }
79 
80 static SexyAL_driver drivers[] =
81 {
82 	#if HAVE_OSSDSP
83 	{ SEXYAL_TYPE_OSSDSP, "OSS(/dev/dsp*)", "oss", SexyALI_OSS_Open, SexyALI_OSS_EnumerateDevices },
84 	#endif
85 
86         #if HAVE_JACK
87         { SEXYAL_TYPE_JACK, "JACK", "jack", SexyALI_JACK_Open, NULL },
88         #endif
89 
90         #if HAVE_SDL
91         { SEXYAL_TYPE_SDL, "SDL", "sdl", SexyALI_SDL_Open, NULL },
92         #endif
93 
94         #if HAVE_ESOUND
95         { SEXYAL_TYPE_ESOUND, "EsounD", "esd", SexyALI_ESD_Open, NULL },
96         #endif
97 
98         #if HAVE_DIRECTSOUND
99         { SEXYAL_TYPE_DIRECTSOUND, "DirectSound", "dsound", SexyALI_DSound_Open, NULL },
100         #endif
101 
102 	{ 0, NULL, NULL, NULL, NULL }
103 };
104 
FindDriver(int type)105 static SexyAL_driver *FindDriver(int type)
106 {
107  int x = 0;
108 
109  while(drivers[x].name)
110  {
111   if(drivers[x].type == type)
112    return(&drivers[x]);
113 
114   x++;
115  }
116  return(0);
117 }
118 
Open(SexyAL * iface,char * id,SexyAL_format * format,SexyAL_buffering * buffering,int type)119 static SexyAL_device *Open(SexyAL *iface, char *id, SexyAL_format *format, SexyAL_buffering *buffering, int type)
120 {
121  SexyAL_device *ret;
122  SexyAL_driver *driver;
123 
124 
125  driver = FindDriver(type);
126  if(!driver)
127   return(0);
128 
129  if(!(ret = driver->Open(id, format, buffering))) return(0);
130 
131  ret->Write=Write;
132  ret->Close=Close;
133  ret->CanWrite=CanWrite;
134  ret->SetConvert=SetConvert;
135 
136  return(ret);
137 }
138 
EnumerateTypes(SexyAL * sal)139 static SexyAL_enumtype *EnumerateTypes(SexyAL *sal)
140 {
141  SexyAL_enumtype *typies;
142  int numdrivers = sizeof(drivers) / sizeof(SexyAL_driver);
143  int x;
144 
145  typies = malloc(numdrivers * sizeof(SexyAL_enumtype));
146  memset(typies, 0, numdrivers * sizeof(SexyAL_enumtype));
147 
148  x = 0;
149 
150  do
151  {
152   typies[x].name = drivers[x].name;
153   typies[x].short_name = drivers[x].short_name;
154   typies[x].type = drivers[x].type;
155  } while(drivers[x++].name);
156 
157  return(typies);
158 }
159 
EnumerateDevices(SexyAL * iface,int type)160 static SexyAL_enumdevice * EnumerateDevices(SexyAL *iface, int type)
161 {
162  SexyAL_driver *driver;
163 
164  driver = FindDriver(type);
165 
166  if(!driver)
167   return(0);
168 
169  if(driver->EnumerateDevices)
170   return(driver->EnumerateDevices());
171 
172  return(0);
173 }
174 
SexyAL_Init(int version)175 void *SexyAL_Init(int version)
176 {
177  SexyAL *iface;
178 
179  iface=malloc(sizeof(SexyAL));
180 
181  iface->Open=Open;
182  iface->Destroy=Destroy;
183 
184  iface->EnumerateTypes = EnumerateTypes;
185  iface->EnumerateDevices = EnumerateDevices;
186  return((void *)iface);
187 }
188