SDL  2.0
SDL_fsaudio.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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_internal.h"
22 
23 #if SDL_AUDIO_DRIVER_FUSIONSOUND
24 
25 /* !!! FIXME: why is this is SDL_FS_* instead of FUSIONSOUND_*? */
26 
27 /* Allow access to a raw mixing buffer */
28 
29 #ifdef HAVE_SIGNAL_H
30 #include <signal.h>
31 #endif
32 #include <unistd.h>
33 
34 #include "SDL_timer.h"
35 #include "SDL_audio.h"
36 #include "../SDL_audio_c.h"
37 #include "SDL_fsaudio.h"
38 
39 #include <fusionsound/fusionsound_version.h>
40 
41 /* #define SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC "libfusionsound.so" */
42 
43 #ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
44 #include "SDL_name.h"
45 #include "SDL_loadso.h"
46 #else
47 #define SDL_NAME(X) X
48 #endif
49 
50 #if (FUSIONSOUND_MAJOR_VERSION == 1) && (FUSIONSOUND_MINOR_VERSION < 1)
51 typedef DFBResult DirectResult;
52 #endif
53 
54 /* Buffers to use - more than 2 gives a lot of latency */
55 #define FUSION_BUFFERS (2)
56 
57 #ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
58 
59 static const char *fs_library = SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC;
60 static void *fs_handle = NULL;
61 
62 static DirectResult (*SDL_NAME(FusionSoundInit)) (int *argc, char *(*argv[]));
63 static DirectResult (*SDL_NAME(FusionSoundCreate)) (IFusionSound **
64  ret_interface);
65 
66 #define SDL_FS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
67 static struct
68 {
69  const char *name;
70  void **func;
71 } fs_functions[] = {
72 /* *INDENT-OFF* */
73  SDL_FS_SYM(FusionSoundInit),
74  SDL_FS_SYM(FusionSoundCreate),
75 /* *INDENT-ON* */
76 };
77 
78 #undef SDL_FS_SYM
79 
80 static void
81 UnloadFusionSoundLibrary()
82 {
83  if (fs_handle != NULL) {
84  SDL_UnloadObject(fs_handle);
85  fs_handle = NULL;
86  }
87 }
88 
89 static int
90 LoadFusionSoundLibrary(void)
91 {
92  int i, retval = -1;
93 
94  if (fs_handle == NULL) {
95  fs_handle = SDL_LoadObject(fs_library);
96  if (fs_handle != NULL) {
97  retval = 0;
98  for (i = 0; i < SDL_arraysize(fs_functions); ++i) {
99  *fs_functions[i].func =
100  SDL_LoadFunction(fs_handle, fs_functions[i].name);
101  if (!*fs_functions[i].func) {
102  retval = -1;
103  UnloadFusionSoundLibrary();
104  break;
105  }
106  }
107  }
108  }
109 
110  return retval;
111 }
112 
113 #else
114 
115 static void
116 UnloadFusionSoundLibrary()
117 {
118  return;
119 }
120 
121 static int
122 LoadFusionSoundLibrary(void)
123 {
124  return 0;
125 }
126 
127 #endif /* SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */
128 
129 /* This function waits until it is possible to write a full sound buffer */
130 static void
131 SDL_FS_WaitDevice(_THIS)
132 {
133  this->hidden->stream->Wait(this->hidden->stream,
134  this->hidden->mixsamples);
135 }
136 
137 static void
138 SDL_FS_PlayDevice(_THIS)
139 {
140  DirectResult ret;
141 
142  ret = this->hidden->stream->Write(this->hidden->stream,
143  this->hidden->mixbuf,
144  this->hidden->mixsamples);
145  /* If we couldn't write, assume fatal error for now */
146  if (ret) {
148  }
149 #ifdef DEBUG_AUDIO
150  fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
151 #endif
152 }
153 
154 
155 static Uint8 *
156 SDL_FS_GetDeviceBuf(_THIS)
157 {
158  return (this->hidden->mixbuf);
159 }
160 
161 
162 static void
163 SDL_FS_CloseDevice(_THIS)
164 {
165  if (this->hidden->stream) {
166  this->hidden->stream->Release(this->hidden->stream);
167  }
168  if (this->hidden->fs) {
169  this->hidden->fs->Release(this->hidden->fs);
170  }
171  SDL_free(this->hidden->mixbuf);
172  SDL_free(this->hidden);
173 }
174 
175 
176 static int
177 SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
178 {
179  int bytes;
180  SDL_AudioFormat test_format = 0, format = 0;
181  FSSampleFormat fs_format;
182  FSStreamDescription desc;
183  DirectResult ret;
184 
185  /* Initialize all variables that we clean on shutdown */
186  this->hidden = (struct SDL_PrivateAudioData *)
187  SDL_malloc((sizeof *this->hidden));
188  if (this->hidden == NULL) {
189  return SDL_OutOfMemory();
190  }
191  SDL_zerop(this->hidden);
192 
193  /* Try for a closest match on audio format */
194  for (test_format = SDL_FirstAudioFormat(this->spec.format);
195  !format && test_format;) {
196 #ifdef DEBUG_AUDIO
197  fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
198 #endif
199  switch (test_format) {
200  case AUDIO_U8:
201  fs_format = FSSF_U8;
202  bytes = 1;
203  format = 1;
204  break;
205  case AUDIO_S16SYS:
206  fs_format = FSSF_S16;
207  bytes = 2;
208  format = 1;
209  break;
210  case AUDIO_S32SYS:
211  fs_format = FSSF_S32;
212  bytes = 4;
213  format = 1;
214  break;
215  case AUDIO_F32SYS:
216  fs_format = FSSF_FLOAT;
217  bytes = 4;
218  format = 1;
219  break;
220  default:
221  format = 0;
222  break;
223  }
224  if (!format) {
225  test_format = SDL_NextAudioFormat();
226  }
227  }
228 
229  if (format == 0) {
230  return SDL_SetError("Couldn't find any hardware audio formats");
231  }
232  this->spec.format = test_format;
233 
234  /* Retrieve the main sound interface. */
235  ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
236  if (ret) {
237  return SDL_SetError("Unable to initialize FusionSound: %d", ret);
238  }
239 
240  this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;
241 
242  /* Fill stream description. */
243  desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
244  FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT | FSSDF_PREBUFFER;
245  desc.samplerate = this->spec.freq;
246  desc.buffersize = this->spec.size * FUSION_BUFFERS;
247  desc.channels = this->spec.channels;
248  desc.prebuffer = 10;
249  desc.sampleformat = fs_format;
250 
251  ret =
252  this->hidden->fs->CreateStream(this->hidden->fs, &desc,
253  &this->hidden->stream);
254  if (ret) {
255  return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
256  }
257 
258  /* See what we got */
259  desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
260  FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT;
261  ret = this->hidden->stream->GetDescription(this->hidden->stream, &desc);
262 
263  this->spec.freq = desc.samplerate;
264  this->spec.size =
265  desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
266  this->spec.channels = desc.channels;
267 
268  /* Calculate the final parameters for this audio specification */
270 
271  /* Allocate mixing buffer */
272  this->hidden->mixlen = this->spec.size;
273  this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
274  if (this->hidden->mixbuf == NULL) {
275  return SDL_OutOfMemory();
276  }
277  SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
278 
279  /* We're ready to rock and roll. :-) */
280  return 0;
281 }
282 
283 
284 static void
285 SDL_FS_Deinitialize(void)
286 {
287  UnloadFusionSoundLibrary();
288 }
289 
290 
291 static int
292 SDL_FS_Init(SDL_AudioDriverImpl * impl)
293 {
294  if (LoadFusionSoundLibrary() < 0) {
295  return 0;
296  } else {
297  DirectResult ret;
298 
299  ret = SDL_NAME(FusionSoundInit) (NULL, NULL);
300  if (ret) {
301  UnloadFusionSoundLibrary();
303  ("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
304  ret);
305  return 0;
306  }
307  }
308 
309  /* Set the function pointers */
310  impl->OpenDevice = SDL_FS_OpenDevice;
311  impl->PlayDevice = SDL_FS_PlayDevice;
312  impl->WaitDevice = SDL_FS_WaitDevice;
313  impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
314  impl->CloseDevice = SDL_FS_CloseDevice;
315  impl->Deinitialize = SDL_FS_Deinitialize;
316  impl->OnlyHasDefaultOutputDevice = 1;
317 
318  return 1; /* this audio target is available. */
319 }
320 
321 
323  "fusionsound", "FusionSound", SDL_FS_Init, 0
324 };
325 
326 #endif /* SDL_AUDIO_DRIVER_FUSIONSOUND */
327 
328 /* vi: set ts=4 sw=4 expandtab: */
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1584
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:449
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
#define SDL_LoadObject
#define AUDIO_S16SYS
Definition: SDL_audio.h:123
#define SDL_UnloadObject
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1596
GLuint const GLchar * name
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioSpec spec
Definition: loopwave.c:31
SDL_bool retval
#define AUDIO_U8
Definition: SDL_audio.h:89
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
AudioBootStrap FUSIONSOUND_bootstrap
Uint8 channels
Definition: SDL_audio.h:181
#define _THIS
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:83
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1605
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
Uint32 size
Definition: SDL_audio.h:185
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_NAME(X)
Definition: SDL_name.h:29
#define SDL_SetError
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:79
GLenum func
SDL_AudioFormat format
Definition: SDL_audio.h:180
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:75
#define AUDIO_S32SYS
Definition: SDL_audio.h:124
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
#define SDL_malloc
void * SDL_LoadFunction(void *handle, const char *name)
#define SDL_memset