zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_fsaudio.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22 
23 #if SDL_AUDIO_DRIVER_FUSIONSOUND
24 
25 /* Allow access to a raw mixing buffer */
26 
27 #ifdef HAVE_SIGNAL_H
28 #include <signal.h>
29 #endif
30 #include <unistd.h>
31 
32 #include "SDL_timer.h"
33 #include "SDL_audio.h"
34 #include "../SDL_audiomem.h"
35 #include "../SDL_audio_c.h"
36 #include "SDL_fsaudio.h"
37 
38 #include <fusionsound/fusionsound_version.h>
39 
40 /* #define SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC "libfusionsound.so" */
41 
42 #ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
43 #include "SDL_name.h"
44 #include "SDL_loadso.h"
45 #else
46 #define SDL_NAME(X) X
47 #endif
48 
49 #if (FUSIONSOUND_MAJOR_VERSION == 1) && (FUSIONSOUND_MINOR_VERSION < 1)
50 typedef DFBResult DirectResult;
51 #endif
52 
53 /* Buffers to use - more than 2 gives a lot of latency */
54 #define FUSION_BUFFERS (2)
55 
56 #ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
57 
58 static const char *fs_library = SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC;
59 static void *fs_handle = NULL;
60 
61 static DirectResult (*SDL_NAME(FusionSoundInit)) (int *argc, char *(*argv[]));
62 static DirectResult (*SDL_NAME(FusionSoundCreate)) (IFusionSound **
63  ret_interface);
64 
65 #define SDL_FS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
66 static struct
67 {
68  const char *name;
69  void **func;
70 } fs_functions[] = {
71 /* *INDENT-OFF* */
72  SDL_FS_SYM(FusionSoundInit),
73  SDL_FS_SYM(FusionSoundCreate),
74 /* *INDENT-ON* */
75 };
76 
77 #undef SDL_FS_SYM
78 
79 static void
80 UnloadFusionSoundLibrary()
81 {
82  if (fs_handle != NULL) {
83  SDL_UnloadObject(fs_handle);
84  fs_handle = NULL;
85  }
86 }
87 
88 static int
89 LoadFusionSoundLibrary(void)
90 {
91  int i, retval = -1;
92 
93  if (fs_handle == NULL) {
94  fs_handle = SDL_LoadObject(fs_library);
95  if (fs_handle != NULL) {
96  retval = 0;
97  for (i = 0; i < SDL_arraysize(fs_functions); ++i) {
98  *fs_functions[i].func =
99  SDL_LoadFunction(fs_handle, fs_functions[i].name);
100  if (!*fs_functions[i].func) {
101  retval = -1;
102  UnloadFusionSoundLibrary();
103  break;
104  }
105  }
106  }
107  }
108 
109  return retval;
110 }
111 
112 #else
113 
114 static void
115 UnloadFusionSoundLibrary()
116 {
117  return;
118 }
119 
120 static int
121 LoadFusionSoundLibrary(void)
122 {
123  return 0;
124 }
125 
126 #endif /* SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */
127 
128 /* This function waits until it is possible to write a full sound buffer */
129 static void
130 SDL_FS_WaitDevice(_THIS)
131 {
132  this->hidden->stream->Wait(this->hidden->stream,
133  this->hidden->mixsamples);
134 }
135 
136 static void
137 SDL_FS_PlayDevice(_THIS)
138 {
139  DirectResult ret;
140 
141  ret = this->hidden->stream->Write(this->hidden->stream,
142  this->hidden->mixbuf,
143  this->hidden->mixsamples);
144  /* If we couldn't write, assume fatal error for now */
145  if (ret) {
146  this->enabled = 0;
147  }
148 #ifdef DEBUG_AUDIO
149  fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
150 #endif
151 }
152 
153 static void
154 SDL_FS_WaitDone(_THIS)
155 {
156  this->hidden->stream->Wait(this->hidden->stream,
157  this->hidden->mixsamples * FUSION_BUFFERS);
158 }
159 
160 
161 static Uint8 *
162 SDL_FS_GetDeviceBuf(_THIS)
163 {
164  return (this->hidden->mixbuf);
165 }
166 
167 
168 static void
169 SDL_FS_CloseDevice(_THIS)
170 {
171  if (this->hidden != NULL) {
172  SDL_FreeAudioMem(this->hidden->mixbuf);
173  this->hidden->mixbuf = NULL;
174  if (this->hidden->stream) {
175  this->hidden->stream->Release(this->hidden->stream);
176  this->hidden->stream = NULL;
177  }
178  if (this->hidden->fs) {
179  this->hidden->fs->Release(this->hidden->fs);
180  this->hidden->fs = NULL;
181  }
182  SDL_free(this->hidden);
183  this->hidden = NULL;
184  }
185 }
186 
187 
188 static int
189 SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
190 {
191  int bytes;
192  SDL_AudioFormat test_format = 0, format = 0;
193  FSSampleFormat fs_format;
194  FSStreamDescription desc;
195  DirectResult ret;
196 
197  /* Initialize all variables that we clean on shutdown */
198  this->hidden = (struct SDL_PrivateAudioData *)
199  SDL_malloc((sizeof *this->hidden));
200  if (this->hidden == NULL) {
201  return SDL_OutOfMemory();
202  }
203  SDL_memset(this->hidden, 0, (sizeof *this->hidden));
204 
205  /* Try for a closest match on audio format */
206  for (test_format = SDL_FirstAudioFormat(this->spec.format);
207  !format && test_format;) {
208 #ifdef DEBUG_AUDIO
209  fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
210 #endif
211  switch (test_format) {
212  case AUDIO_U8:
213  fs_format = FSSF_U8;
214  bytes = 1;
215  format = 1;
216  break;
217  case AUDIO_S16SYS:
218  fs_format = FSSF_S16;
219  bytes = 2;
220  format = 1;
221  break;
222  case AUDIO_S32SYS:
223  fs_format = FSSF_S32;
224  bytes = 4;
225  format = 1;
226  break;
227  case AUDIO_F32SYS:
228  fs_format = FSSF_FLOAT;
229  bytes = 4;
230  format = 1;
231  break;
232  default:
233  format = 0;
234  break;
235  }
236  if (!format) {
237  test_format = SDL_NextAudioFormat();
238  }
239  }
240 
241  if (format == 0) {
242  SDL_FS_CloseDevice(this);
243  return SDL_SetError("Couldn't find any hardware audio formats");
244  }
245  this->spec.format = test_format;
246 
247  /* Retrieve the main sound interface. */
248  ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
249  if (ret) {
250  SDL_FS_CloseDevice(this);
251  return SDL_SetError("Unable to initialize FusionSound: %d", ret);
252  }
253 
254  this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;
255 
256  /* Fill stream description. */
257  desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
258  FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT | FSSDF_PREBUFFER;
259  desc.samplerate = this->spec.freq;
260  desc.buffersize = this->spec.size * FUSION_BUFFERS;
261  desc.channels = this->spec.channels;
262  desc.prebuffer = 10;
263  desc.sampleformat = fs_format;
264 
265  ret =
266  this->hidden->fs->CreateStream(this->hidden->fs, &desc,
267  &this->hidden->stream);
268  if (ret) {
269  SDL_FS_CloseDevice(this);
270  return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
271  }
272 
273  /* See what we got */
274  desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
275  FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT;
276  ret = this->hidden->stream->GetDescription(this->hidden->stream, &desc);
277 
278  this->spec.freq = desc.samplerate;
279  this->spec.size =
280  desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
281  this->spec.channels = desc.channels;
282 
283  /* Calculate the final parameters for this audio specification */
284  SDL_CalculateAudioSpec(&this->spec);
285 
286  /* Allocate mixing buffer */
287  this->hidden->mixlen = this->spec.size;
288  this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
289  if (this->hidden->mixbuf == NULL) {
290  SDL_FS_CloseDevice(this);
291  return SDL_OutOfMemory();
292  }
293  SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
294 
295  /* We're ready to rock and roll. :-) */
296  return 0;
297 }
298 
299 
300 static void
301 SDL_FS_Deinitialize(void)
302 {
303  UnloadFusionSoundLibrary();
304 }
305 
306 
307 static int
308 SDL_FS_Init(SDL_AudioDriverImpl * impl)
309 {
310  if (LoadFusionSoundLibrary() < 0) {
311  return 0;
312  } else {
313  DirectResult ret;
314 
315  ret = SDL_NAME(FusionSoundInit) (NULL, NULL);
316  if (ret) {
317  UnloadFusionSoundLibrary();
319  ("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
320  ret);
321  return 0;
322  }
323  }
324 
325  /* Set the function pointers */
326  impl->OpenDevice = SDL_FS_OpenDevice;
327  impl->PlayDevice = SDL_FS_PlayDevice;
328  impl->WaitDevice = SDL_FS_WaitDevice;
329  impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
330  impl->CloseDevice = SDL_FS_CloseDevice;
331  impl->WaitDone = SDL_FS_WaitDone;
332  impl->Deinitialize = SDL_FS_Deinitialize;
333  impl->OnlyHasDefaultOutputDevice = 1;
334 
335  return 1; /* this audio target is available. */
336 }
337 
338 
340  "fusionsound", "FusionSound", SDL_FS_Init, 0
341 };
342 
343 #endif /* SDL_AUDIO_DRIVER_FUSIONSOUND */
344 
345 /* vi: set ts=4 sw=4 expandtab: */
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:45
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1226
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:41
#define NULL
Definition: ftobjs.h:61
GLenum GLsizei const GLuint GLboolean enabled
Definition: glew.h:2538
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:43
#define SDL_FreeAudioMem
Definition: SDL_audiomem.h:24
DECLSPEC void SDLCALL SDL_free(void *mem)
EGLImageKHR EGLint * name
Definition: eglext.h:284
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
void(* WaitDone)(_THIS)
Definition: SDL_sysaudio.h:44
#define AUDIO_S16SYS
Definition: SDL_audio.h:123
GLenum func
Definition: SDL_opengl.h:5654
int(* OpenDevice)(_THIS, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:39
ret
Definition: glew_str_glx.c:2
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1238
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:42
#define AUDIO_U8
Definition: SDL_audio.h:89
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
#define _THIS
DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile)
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
DECLSPEC void SDLCALL SDL_UnloadObject(void *handle)
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1247
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:48
#define SDL_AllocAudioMem
Definition: SDL_audiomem.h:23
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
#define SDL_NAME(X)
Definition: SDL_name.h:9
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
#define AUDIO_S32SYS
Definition: SDL_audio.h:124
int i
Definition: pngrutil.c:1377
DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle, const char *name)
AudioBootStrap FUSIONSOUND_bootstrap