src/audio/haiku/SDL_haikuaudio.cc
author Ryan C. Gordon <icculus@icculus.org>
Mon, 21 May 2018 12:00:21 -0400
changeset 11994 8e094f91ddab
parent 11811 5d94cb6b24d3
child 12503 806492103856
permissions -rw-r--r--
thread: fixed compiler warnings on non-Linux systems that use pthread.

(static function rtkit_setpriority was unused, moved it in with rest of
__LINUX__ section.)
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 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@10997
    51
    SDL_AudioCallback callback = audio->callbackspec.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@10997
    66
        callback(audio->callbackspec.userdata, (Uint8 *) 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@10997
    72
            callback(audio->callbackspec.userdata, audio->work_buffer, stream_len);
icculus@10765
    73
            if (SDL_AudioStreamPut(audio->stream, audio->work_buffer, 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: */