~brandontschaefer/+junk/sdl-mir-support-v2

« back to all changes in this revision

Viewing changes to src/audio/fusionsound/SDL_fsaudio.c

  • Committer: Brandon Schaefer
  • Date: 2013-12-19 23:38:26 UTC
  • Revision ID: brandontschaefer@gmail.com-20131219233826-3jipv3mkvm8ajt1r
* Trunk SDL2 Rev: 8064

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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();
 
318
            SDL_SetError
 
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
 
 
339
AudioBootStrap FUSIONSOUND_bootstrap = {
 
340
    "fusionsound", "FusionSound", SDL_FS_Init, 0
 
341
};
 
342
 
 
343
#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND */
 
344
 
 
345
/* vi: set ts=4 sw=4 expandtab: */