src/audio/baudio/SDL_beaudio.cc
author Ryan C. Gordon <icculus@icculus.org>
Wed, 13 Nov 2013 22:35:26 -0500
changeset 7977 5272ae8fccd7
parent 7038 7f22b9ba218f
child 7979 93d31af030bc
permissions -rw-r--r--
Started BeOS removal: merged BeOS thread and pthread code.

Haiku uses most of the standard pthread API, with a few #ifdefs where we
still need to fallback onto the old BeOS APIs.

BeOS, however, does not support pthreads (or maybe doesn't support it well),
so I'm unplugging support for the platform with this changeset. Be Inc went
out of business in 2001.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 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
*/
slouken@1403
    21
#include "SDL_config.h"
slouken@0
    22
slouken@6044
    23
#if SDL_AUDIO_DRIVER_BEOSAUDIO
slouken@6044
    24
slouken@0
    25
/* Allow access to the audio stream on BeOS */
slouken@0
    26
slouken@0
    27
#include <SoundPlayer.h>
icculus@7977
    28
#include <signal.h>
slouken@0
    29
slouken@1367
    30
#include "../../main/beos/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"
slouken@1367
    38
#include "../../thread/beos/SDL_systhread_c.h"
slouken@0
    39
#include "SDL_beaudio.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@2049
    45
/* The BeOS 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;
slouken@0
    51
icculus@2049
    52
    /* Only do soemthing if audio is enabled */
icculus@2049
    53
    if (!audio->enabled)
icculus@2049
    54
        return;
slouken@0
    55
icculus@2049
    56
    if (!audio->paused) {
icculus@2049
    57
        if (audio->convert.needed) {
slouken@6977
    58
            SDL_LockMutex(audio->mixer_lock);
icculus@2049
    59
            (*audio->spec.callback) (audio->spec.userdata,
slouken@2060
    60
                                     (Uint8 *) audio->convert.buf,
slouken@2060
    61
                                     audio->convert.len);
slouken@6977
    62
            SDL_UnlockMutex(audio->mixer_lock);
icculus@2049
    63
            SDL_ConvertAudio(&audio->convert);
icculus@2049
    64
            SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
icculus@2049
    65
        } else {
slouken@6977
    66
            SDL_LockMutex(audio->mixer_lock);
icculus@2049
    67
            (*audio->spec.callback) (audio->spec.userdata,
slouken@2060
    68
                                     (Uint8 *) stream, len);
slouken@6977
    69
            SDL_UnlockMutex(audio->mixer_lock);
slouken@1895
    70
        }
slouken@1895
    71
    }
icculus@2049
    72
}
slouken@0
    73
icculus@2049
    74
static void
icculus@2049
    75
BEOSAUDIO_CloseDevice(_THIS)
icculus@2049
    76
{
icculus@2049
    77
    if (_this->hidden != NULL) {
icculus@2049
    78
        if (_this->hidden->audio_obj) {
icculus@2049
    79
            _this->hidden->audio_obj->Stop();
icculus@2049
    80
            delete _this->hidden->audio_obj;
icculus@2049
    81
            _this->hidden->audio_obj = NULL;
slouken@1895
    82
        }
slouken@0
    83
icculus@2049
    84
        delete _this->hidden;
icculus@2049
    85
        _this->hidden = NULL;
slouken@1895
    86
    }
icculus@2049
    87
}
slouken@0
    88
icculus@7977
    89
icculus@7977
    90
static const int sig_list[] = {
icculus@7977
    91
    SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0
icculus@7977
    92
};
icculus@7977
    93
icculus@7977
    94
static inline void
icculus@7977
    95
MaskSignals(sigset_t * omask)
icculus@7977
    96
{
icculus@7977
    97
    sigset_t mask;
icculus@7977
    98
    int i;
icculus@7977
    99
icculus@7977
   100
    sigemptyset(&mask);
icculus@7977
   101
    for (i = 0; sig_list[i]; ++i) {
icculus@7977
   102
        sigaddset(&mask, sig_list[i]);
icculus@7977
   103
    }
icculus@7977
   104
    sigprocmask(SIG_BLOCK, &mask, omask);
icculus@7977
   105
}
icculus@7977
   106
icculus@7977
   107
static inline void
icculus@7977
   108
UnmaskSignals(sigset_t * omask)
icculus@7977
   109
{
icculus@7977
   110
    sigprocmask(SIG_SETMASK, omask, NULL);
icculus@7977
   111
}
icculus@7977
   112
icculus@7977
   113
icculus@2049
   114
static int
icculus@2049
   115
BEOSAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
icculus@2049
   116
{
icculus@2049
   117
    int valid_datatype = 0;
icculus@2049
   118
    media_raw_audio_format format;
icculus@2049
   119
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
icculus@1997
   120
icculus@2049
   121
    /* Initialize all variables that we clean on shutdown */
icculus@2049
   122
    _this->hidden = new SDL_PrivateAudioData;
icculus@2049
   123
    if (_this->hidden == NULL) {
icculus@7038
   124
        return SDL_OutOfMemory();
icculus@2049
   125
    }
icculus@2049
   126
    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
icculus@2049
   127
icculus@2049
   128
    /* Parse the audio format and fill the Be raw audio format */
icculus@2049
   129
    SDL_memset(&format, '\0', sizeof(media_raw_audio_format));
icculus@2049
   130
    format.byte_order = B_MEDIA_LITTLE_ENDIAN;
icculus@2049
   131
    format.frame_rate = (float) _this->spec.freq;
slouken@2060
   132
    format.channel_count = _this->spec.channels;        /* !!! FIXME: support > 2? */
icculus@2049
   133
    while ((!valid_datatype) && (test_format)) {
icculus@2049
   134
        valid_datatype = 1;
icculus@2049
   135
        _this->spec.format = test_format;
icculus@2049
   136
        switch (test_format) {
slouken@2060
   137
        case AUDIO_S8:
slouken@2060
   138
            format.format = media_raw_audio_format::B_AUDIO_CHAR;
slouken@2060
   139
            break;
icculus@1997
   140
slouken@2060
   141
        case AUDIO_U8:
slouken@2060
   142
            format.format = media_raw_audio_format::B_AUDIO_UCHAR;
slouken@2060
   143
            break;
icculus@1997
   144
slouken@2060
   145
        case AUDIO_S16LSB:
slouken@2060
   146
            format.format = media_raw_audio_format::B_AUDIO_SHORT;
slouken@2060
   147
            break;
icculus@1997
   148
slouken@2060
   149
        case AUDIO_S16MSB:
slouken@2060
   150
            format.format = media_raw_audio_format::B_AUDIO_SHORT;
slouken@2060
   151
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   152
            break;
icculus@1997
   153
slouken@2060
   154
        case AUDIO_S32LSB:
slouken@2060
   155
            format.format = media_raw_audio_format::B_AUDIO_INT;
slouken@2060
   156
            break;
icculus@1997
   157
slouken@2060
   158
        case AUDIO_S32MSB:
slouken@2060
   159
            format.format = media_raw_audio_format::B_AUDIO_INT;
slouken@2060
   160
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   161
            break;
icculus@1997
   162
slouken@2060
   163
        case AUDIO_F32LSB:
slouken@2060
   164
            format.format = media_raw_audio_format::B_AUDIO_FLOAT;
slouken@2060
   165
            break;
icculus@1997
   166
slouken@2060
   167
        case AUDIO_F32MSB:
slouken@2060
   168
            format.format = media_raw_audio_format::B_AUDIO_FLOAT;
slouken@2060
   169
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   170
            break;
icculus@1997
   171
slouken@2060
   172
        default:
slouken@2060
   173
            valid_datatype = 0;
slouken@2060
   174
            test_format = SDL_NextAudioFormat();
slouken@2060
   175
            break;
icculus@1997
   176
        }
slouken@1895
   177
    }
slouken@1895
   178
slouken@2060
   179
    if (!valid_datatype) {      /* shouldn't happen, but just in case... */
icculus@2049
   180
        BEOSAUDIO_CloseDevice(_this);
icculus@7038
   181
        return SDL_SetError("Unsupported audio format");
icculus@2049
   182
    }
icculus@2049
   183
icculus@2049
   184
    /* Calculate the final parameters for this audio specification */
icculus@2049
   185
    SDL_CalculateAudioSpec(&_this->spec);
icculus@2049
   186
slouken@6856
   187
    format.buffer_size = _this->spec.size;
slouken@6856
   188
icculus@2049
   189
    /* Subscribe to the audio stream (creates a new thread) */
icculus@2049
   190
    sigset_t omask;
icculus@7977
   191
    MaskSignals(&omask);
icculus@2049
   192
    _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
icculus@2049
   193
                                                FillSound, NULL, _this);
icculus@7977
   194
    UnmaskSignals(&omask);
icculus@2049
   195
icculus@2049
   196
    if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
icculus@2049
   197
        _this->hidden->audio_obj->SetHasData(true);
icculus@2049
   198
    } else {
icculus@2049
   199
        BEOSAUDIO_CloseDevice(_this);
icculus@7038
   200
        return SDL_SetError("Unable to start Be audio");
icculus@2049
   201
    }
icculus@2049
   202
icculus@2049
   203
    /* We're running! */
icculus@7038
   204
    return 0;
icculus@2049
   205
}
icculus@2049
   206
icculus@2049
   207
static void
icculus@2049
   208
BEOSAUDIO_Deinitialize(void)
icculus@2049
   209
{
icculus@2049
   210
    SDL_QuitBeApp();
icculus@2049
   211
}
icculus@2049
   212
icculus@2049
   213
static int
slouken@2060
   214
BEOSAUDIO_Init(SDL_AudioDriverImpl * impl)
icculus@2049
   215
{
icculus@2049
   216
    /* Initialize the Be Application, if it's not already started */
icculus@2049
   217
    if (SDL_InitBeApp() < 0) {
icculus@2049
   218
        return 0;
icculus@2049
   219
    }
icculus@2049
   220
icculus@2049
   221
    /* Set the function pointers */
icculus@2049
   222
    impl->OpenDevice = BEOSAUDIO_OpenDevice;
icculus@2049
   223
    impl->CloseDevice = BEOSAUDIO_CloseDevice;
icculus@2049
   224
    impl->Deinitialize = BEOSAUDIO_Deinitialize;
icculus@2049
   225
    impl->ProvidesOwnCallbackThread = 1;
icculus@2049
   226
    impl->OnlyHasDefaultOutputDevice = 1;
icculus@2049
   227
icculus@3699
   228
    return 1;   /* this audio target is available. */
icculus@2049
   229
}
icculus@2049
   230
slouken@2060
   231
extern "C"
slouken@2060
   232
{
slouken@2060
   233
    extern AudioBootStrap BEOSAUDIO_bootstrap;
slouken@2060
   234
}
icculus@2049
   235
AudioBootStrap BEOSAUDIO_bootstrap = {
icculus@2049
   236
    "baudio", "BeOS BSoundPlayer", BEOSAUDIO_Init, 0
icculus@2049
   237
};
slouken@1895
   238
slouken@6044
   239
#endif /* SDL_AUDIO_DRIVER_BEOSAUDIO */
slouken@6044
   240
slouken@1895
   241
/* vi: set ts=4 sw=4 expandtab: */