src/audio/haiku/SDL_haikuaudio.cc
author Ryan C. Gordon <icculus@icculus.org>
Fri, 06 Jan 2017 01:02:58 -0500
changeset 10764 f9bf759e9dd1
parent 10762 4b1b1918a246
child 10765 61312c8c59fe
permissions -rw-r--r--
audio: Fixed SDL_AudioStreamGet() function parameters.

There was a draft of this where it did audio conversion into the final buffer,
if there was enough room available past what you asked for, but that interface
got removed, so the parameters didn't make sense (and we were using the
wrong one in any case, too!).
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@0
    22
icculus@7981
    23
#if SDL_AUDIO_DRIVER_HAIKU
slouken@6044
    24
icculus@7981
    25
/* Allow access to the audio stream on Haiku */
slouken@0
    26
slouken@0
    27
#include <SoundPlayer.h>
icculus@7977
    28
#include <signal.h>
slouken@0
    29
icculus@7981
    30
#include "../../main/haiku/SDL_BeApp.h"
slouken@0
    31
slouken@1895
    32
extern "C"
slouken@1895
    33
{
slouken@0
    34
slouken@0
    35
#include "SDL_audio.h"
slouken@1361
    36
#include "../SDL_audio_c.h"
slouken@1361
    37
#include "../SDL_sysaudio.h"
icculus@7981
    38
#include "SDL_haikuaudio.h"
icculus@10762
    39
#include "SDL_assert.h"
slouken@0
    40
icculus@2049
    41
}
slouken@0
    42
slouken@0
    43
icculus@2049
    44
/* !!! FIXME: have the callback call the higher level to avoid code dupe. */
icculus@7981
    45
/* The Haiku callback for handling the audio buffer */
icculus@2049
    46
static void
icculus@2049
    47
FillSound(void *device, void *stream, size_t len,
icculus@2049
    48
          const media_raw_audio_format & format)
icculus@2049
    49
{
icculus@2049
    50
    SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
icculus@10762
    51
    SDL_AudioCallback callback = audio->spec.callback;
slouken@0
    52
icculus@10762
    53
    /* Only do something if audio is enabled */
icculus@10762
    54
    if (!SDL_AtomicGet(&audio->enabled) || SDL_AtomicGet(&audio->paused)) {
icculus@10762
    55
        if (audio->stream) {
icculus@10762
    56
            SDL_AudioStreamClear(audio->stream);
icculus@10762
    57
        }
icculus@10762
    58
        SDL_memset(stream, audio->spec.silence, len);
icculus@2049
    59
        return;
icculus@10238
    60
    }
slouken@0
    61
icculus@10762
    62
    SDL_assert(audio->spec.size == len);
icculus@10762
    63
icculus@10762
    64
    if (audio->stream == NULL) {  /* no conversion necessary. */
icculus@10762
    65
        SDL_LockMutex(audio->mixer_lock);
icculus@10762
    66
        callback(audio->spec.userdata, stream, len);
icculus@10762
    67
        SDL_UnlockMutex(audio->mixer_lock);
icculus@10762
    68
    } else {  /* streaming/converting */
icculus@10762
    69
        const int stream_len = audio->callbackspec.size;
icculus@10762
    70
        const int ilen = (int) len;
icculus@10762
    71
        while (SDL_AudioStreamAvailable(audio->stream) < ilen) {
icculus@10762
    72
            callback(audio->spec.userdata, audio->fake_stream, stream_len);
icculus@10762
    73
            if (SDL_AudioStreamPut(audio->stream, audio->fake_stream, stream_len) == -1) {
icculus@10762
    74
                SDL_AudioStreamClear(audio->stream);
icculus@10762
    75
                SDL_AtomicSet(&audio->enabled, 0);
icculus@10762
    76
                break;
icculus@10762
    77
            }
icculus@10762
    78
        }
icculus@10762
    79
icculus@10764
    80
        const int got = SDL_AudioStreamGet(audio->stream, stream, ilen);
icculus@10762
    81
        SDL_assert((got < 0) || (got == ilen));
icculus@10762
    82
        if (got != ilen) {
icculus@10762
    83
            SDL_memset(stream, audio->spec.silence, len);
slouken@1895
    84
        }
slouken@1895
    85
    }
icculus@2049
    86
}
slouken@0
    87
icculus@2049
    88
static void
icculus@7981
    89
HAIKUAUDIO_CloseDevice(_THIS)
icculus@2049
    90
{
icculus@10255
    91
    if (_this->hidden->audio_obj) {
icculus@10255
    92
        _this->hidden->audio_obj->Stop();
icculus@10255
    93
        delete _this->hidden->audio_obj;
slouken@1895
    94
    }
icculus@10255
    95
    delete _this->hidden;
icculus@2049
    96
}
slouken@0
    97
icculus@7977
    98
icculus@7977
    99
static const int sig_list[] = {
icculus@7977
   100
    SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0
icculus@7977
   101
};
icculus@7977
   102
icculus@7977
   103
static inline void
icculus@7977
   104
MaskSignals(sigset_t * omask)
icculus@7977
   105
{
icculus@7977
   106
    sigset_t mask;
icculus@7977
   107
    int i;
icculus@7977
   108
icculus@7977
   109
    sigemptyset(&mask);
icculus@7977
   110
    for (i = 0; sig_list[i]; ++i) {
icculus@7977
   111
        sigaddset(&mask, sig_list[i]);
icculus@7977
   112
    }
icculus@7977
   113
    sigprocmask(SIG_BLOCK, &mask, omask);
icculus@7977
   114
}
icculus@7977
   115
icculus@7977
   116
static inline void
icculus@7977
   117
UnmaskSignals(sigset_t * omask)
icculus@7977
   118
{
icculus@7977
   119
    sigprocmask(SIG_SETMASK, omask, NULL);
icculus@7977
   120
}
icculus@7977
   121
icculus@7977
   122
icculus@2049
   123
static int
icculus@9394
   124
HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
icculus@2049
   125
{
icculus@2049
   126
    int valid_datatype = 0;
icculus@2049
   127
    media_raw_audio_format format;
icculus@2049
   128
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
icculus@1997
   129
icculus@2049
   130
    /* Initialize all variables that we clean on shutdown */
icculus@2049
   131
    _this->hidden = new SDL_PrivateAudioData;
icculus@2049
   132
    if (_this->hidden == NULL) {
icculus@7038
   133
        return SDL_OutOfMemory();
icculus@2049
   134
    }
icculus@10287
   135
    SDL_zerop(_this->hidden);
icculus@2049
   136
icculus@2049
   137
    /* Parse the audio format and fill the Be raw audio format */
icculus@10257
   138
    SDL_zero(format);
icculus@2049
   139
    format.byte_order = B_MEDIA_LITTLE_ENDIAN;
icculus@2049
   140
    format.frame_rate = (float) _this->spec.freq;
slouken@2060
   141
    format.channel_count = _this->spec.channels;        /* !!! FIXME: support > 2? */
icculus@2049
   142
    while ((!valid_datatype) && (test_format)) {
icculus@2049
   143
        valid_datatype = 1;
icculus@2049
   144
        _this->spec.format = test_format;
icculus@2049
   145
        switch (test_format) {
slouken@2060
   146
        case AUDIO_S8:
slouken@2060
   147
            format.format = media_raw_audio_format::B_AUDIO_CHAR;
slouken@2060
   148
            break;
icculus@1997
   149
slouken@2060
   150
        case AUDIO_U8:
slouken@2060
   151
            format.format = media_raw_audio_format::B_AUDIO_UCHAR;
slouken@2060
   152
            break;
icculus@1997
   153
slouken@2060
   154
        case AUDIO_S16LSB:
slouken@2060
   155
            format.format = media_raw_audio_format::B_AUDIO_SHORT;
slouken@2060
   156
            break;
icculus@1997
   157
slouken@2060
   158
        case AUDIO_S16MSB:
slouken@2060
   159
            format.format = media_raw_audio_format::B_AUDIO_SHORT;
slouken@2060
   160
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   161
            break;
icculus@1997
   162
slouken@2060
   163
        case AUDIO_S32LSB:
slouken@2060
   164
            format.format = media_raw_audio_format::B_AUDIO_INT;
slouken@2060
   165
            break;
icculus@1997
   166
slouken@2060
   167
        case AUDIO_S32MSB:
slouken@2060
   168
            format.format = media_raw_audio_format::B_AUDIO_INT;
slouken@2060
   169
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   170
            break;
icculus@1997
   171
slouken@2060
   172
        case AUDIO_F32LSB:
slouken@2060
   173
            format.format = media_raw_audio_format::B_AUDIO_FLOAT;
slouken@2060
   174
            break;
icculus@1997
   175
slouken@2060
   176
        case AUDIO_F32MSB:
slouken@2060
   177
            format.format = media_raw_audio_format::B_AUDIO_FLOAT;
slouken@2060
   178
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   179
            break;
icculus@1997
   180
slouken@2060
   181
        default:
slouken@2060
   182
            valid_datatype = 0;
slouken@2060
   183
            test_format = SDL_NextAudioFormat();
slouken@2060
   184
            break;
icculus@1997
   185
        }
slouken@1895
   186
    }
slouken@1895
   187
slouken@2060
   188
    if (!valid_datatype) {      /* shouldn't happen, but just in case... */
icculus@7038
   189
        return SDL_SetError("Unsupported audio format");
icculus@2049
   190
    }
icculus@2049
   191
icculus@2049
   192
    /* Calculate the final parameters for this audio specification */
icculus@2049
   193
    SDL_CalculateAudioSpec(&_this->spec);
icculus@2049
   194
slouken@6856
   195
    format.buffer_size = _this->spec.size;
slouken@6856
   196
icculus@2049
   197
    /* Subscribe to the audio stream (creates a new thread) */
icculus@2049
   198
    sigset_t omask;
icculus@7977
   199
    MaskSignals(&omask);
icculus@2049
   200
    _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
icculus@2049
   201
                                                FillSound, NULL, _this);
icculus@7977
   202
    UnmaskSignals(&omask);
icculus@2049
   203
icculus@2049
   204
    if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
icculus@2049
   205
        _this->hidden->audio_obj->SetHasData(true);
icculus@2049
   206
    } else {
icculus@7038
   207
        return SDL_SetError("Unable to start Be audio");
icculus@2049
   208
    }
icculus@2049
   209
icculus@2049
   210
    /* We're running! */
icculus@7038
   211
    return 0;
icculus@2049
   212
}
icculus@2049
   213
icculus@2049
   214
static void
icculus@7981
   215
HAIKUAUDIO_Deinitialize(void)
icculus@2049
   216
{
icculus@2049
   217
    SDL_QuitBeApp();
icculus@2049
   218
}
icculus@2049
   219
icculus@2049
   220
static int
icculus@7981
   221
HAIKUAUDIO_Init(SDL_AudioDriverImpl * impl)
icculus@2049
   222
{
icculus@2049
   223
    /* Initialize the Be Application, if it's not already started */
icculus@2049
   224
    if (SDL_InitBeApp() < 0) {
icculus@2049
   225
        return 0;
icculus@2049
   226
    }
icculus@2049
   227
icculus@2049
   228
    /* Set the function pointers */
icculus@7981
   229
    impl->OpenDevice = HAIKUAUDIO_OpenDevice;
icculus@7981
   230
    impl->CloseDevice = HAIKUAUDIO_CloseDevice;
icculus@7981
   231
    impl->Deinitialize = HAIKUAUDIO_Deinitialize;
icculus@2049
   232
    impl->ProvidesOwnCallbackThread = 1;
icculus@2049
   233
    impl->OnlyHasDefaultOutputDevice = 1;
icculus@2049
   234
icculus@3699
   235
    return 1;   /* this audio target is available. */
icculus@2049
   236
}
icculus@2049
   237
slouken@2060
   238
extern "C"
slouken@2060
   239
{
icculus@7981
   240
    extern AudioBootStrap HAIKUAUDIO_bootstrap;
slouken@2060
   241
}
icculus@7981
   242
AudioBootStrap HAIKUAUDIO_bootstrap = {
icculus@7981
   243
    "haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, 0
icculus@2049
   244
};
slouken@1895
   245
icculus@7981
   246
#endif /* SDL_AUDIO_DRIVER_HAIKU */
slouken@6044
   247
slouken@1895
   248
/* vi: set ts=4 sw=4 expandtab: */