src/audio/baudio/SDL_beaudio.cc
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 22:37:15 -0800
changeset 5262 b530ef003506
parent 3699 4160ba33b597
child 5535 96594ac5fd1a
permissions -rw-r--r--
Happy 2011! :)
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@5262
     3
    Copyright (C) 1997-2011 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1403
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* Allow access to the audio stream on BeOS */
slouken@0
    25
slouken@0
    26
#include <SoundPlayer.h>
slouken@0
    27
slouken@1367
    28
#include "../../main/beos/SDL_BeApp.h"
slouken@0
    29
slouken@1895
    30
extern "C"
slouken@1895
    31
{
slouken@0
    32
slouken@0
    33
#include "SDL_audio.h"
slouken@1361
    34
#include "../SDL_audio_c.h"
slouken@1361
    35
#include "../SDL_sysaudio.h"
slouken@1367
    36
#include "../../thread/beos/SDL_systhread_c.h"
slouken@0
    37
#include "SDL_beaudio.h"
slouken@0
    38
icculus@2049
    39
}
slouken@0
    40
slouken@0
    41
icculus@2049
    42
/* !!! FIXME: have the callback call the higher level to avoid code dupe. */
icculus@2049
    43
/* The BeOS callback for handling the audio buffer */
icculus@2049
    44
static void
icculus@2049
    45
FillSound(void *device, void *stream, size_t len,
icculus@2049
    46
          const media_raw_audio_format & format)
icculus@2049
    47
{
icculus@2049
    48
    SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
slouken@0
    49
icculus@2049
    50
    /* Silence the buffer, since it's ours */
icculus@2049
    51
    SDL_memset(stream, audio->spec.silence, len);
slouken@0
    52
icculus@2049
    53
    /* Only do soemthing if audio is enabled */
icculus@2049
    54
    if (!audio->enabled)
icculus@2049
    55
        return;
slouken@0
    56
icculus@2049
    57
    if (!audio->paused) {
icculus@2049
    58
        if (audio->convert.needed) {
icculus@2049
    59
            SDL_mutexP(audio->mixer_lock);
icculus@2049
    60
            (*audio->spec.callback) (audio->spec.userdata,
slouken@2060
    61
                                     (Uint8 *) audio->convert.buf,
slouken@2060
    62
                                     audio->convert.len);
icculus@2049
    63
            SDL_mutexV(audio->mixer_lock);
icculus@2049
    64
            SDL_ConvertAudio(&audio->convert);
icculus@2049
    65
            SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
icculus@2049
    66
        } else {
icculus@2049
    67
            SDL_mutexP(audio->mixer_lock);
icculus@2049
    68
            (*audio->spec.callback) (audio->spec.userdata,
slouken@2060
    69
                                     (Uint8 *) stream, len);
icculus@2049
    70
            SDL_mutexV(audio->mixer_lock);
slouken@1895
    71
        }
slouken@1895
    72
    }
icculus@2049
    73
}
slouken@0
    74
icculus@2049
    75
static void
icculus@2049
    76
BEOSAUDIO_CloseDevice(_THIS)
icculus@2049
    77
{
icculus@2049
    78
    if (_this->hidden != NULL) {
icculus@2049
    79
        if (_this->hidden->audio_obj) {
icculus@2049
    80
            _this->hidden->audio_obj->Stop();
icculus@2049
    81
            delete _this->hidden->audio_obj;
icculus@2049
    82
            _this->hidden->audio_obj = NULL;
slouken@1895
    83
        }
slouken@0
    84
icculus@2049
    85
        delete _this->hidden;
icculus@2049
    86
        _this->hidden = NULL;
slouken@1895
    87
    }
icculus@2049
    88
}
slouken@0
    89
icculus@2049
    90
static int
icculus@2049
    91
BEOSAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
icculus@2049
    92
{
icculus@2049
    93
    int valid_datatype = 0;
icculus@2049
    94
    media_raw_audio_format format;
icculus@2049
    95
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
icculus@1997
    96
icculus@2049
    97
    /* Initialize all variables that we clean on shutdown */
icculus@2049
    98
    _this->hidden = new SDL_PrivateAudioData;
icculus@2049
    99
    if (_this->hidden == NULL) {
icculus@2049
   100
        SDL_OutOfMemory();
icculus@2049
   101
        return 0;
icculus@2049
   102
    }
icculus@2049
   103
    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
icculus@2049
   104
icculus@2049
   105
    /* Parse the audio format and fill the Be raw audio format */
icculus@2049
   106
    SDL_memset(&format, '\0', sizeof(media_raw_audio_format));
icculus@2049
   107
    format.byte_order = B_MEDIA_LITTLE_ENDIAN;
icculus@2049
   108
    format.frame_rate = (float) _this->spec.freq;
slouken@2060
   109
    format.channel_count = _this->spec.channels;        /* !!! FIXME: support > 2? */
icculus@2049
   110
    while ((!valid_datatype) && (test_format)) {
icculus@2049
   111
        valid_datatype = 1;
icculus@2049
   112
        _this->spec.format = test_format;
icculus@2049
   113
        switch (test_format) {
slouken@2060
   114
        case AUDIO_S8:
slouken@2060
   115
            format.format = media_raw_audio_format::B_AUDIO_CHAR;
slouken@2060
   116
            break;
icculus@1997
   117
slouken@2060
   118
        case AUDIO_U8:
slouken@2060
   119
            format.format = media_raw_audio_format::B_AUDIO_UCHAR;
slouken@2060
   120
            break;
icculus@1997
   121
slouken@2060
   122
        case AUDIO_S16LSB:
slouken@2060
   123
            format.format = media_raw_audio_format::B_AUDIO_SHORT;
slouken@2060
   124
            break;
icculus@1997
   125
slouken@2060
   126
        case AUDIO_S16MSB:
slouken@2060
   127
            format.format = media_raw_audio_format::B_AUDIO_SHORT;
slouken@2060
   128
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   129
            break;
icculus@1997
   130
slouken@2060
   131
        case AUDIO_S32LSB:
slouken@2060
   132
            format.format = media_raw_audio_format::B_AUDIO_INT;
slouken@2060
   133
            break;
icculus@1997
   134
slouken@2060
   135
        case AUDIO_S32MSB:
slouken@2060
   136
            format.format = media_raw_audio_format::B_AUDIO_INT;
slouken@2060
   137
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   138
            break;
icculus@1997
   139
slouken@2060
   140
        case AUDIO_F32LSB:
slouken@2060
   141
            format.format = media_raw_audio_format::B_AUDIO_FLOAT;
slouken@2060
   142
            break;
icculus@1997
   143
slouken@2060
   144
        case AUDIO_F32MSB:
slouken@2060
   145
            format.format = media_raw_audio_format::B_AUDIO_FLOAT;
slouken@2060
   146
            format.byte_order = B_MEDIA_BIG_ENDIAN;
slouken@2060
   147
            break;
icculus@1997
   148
slouken@2060
   149
        default:
slouken@2060
   150
            valid_datatype = 0;
slouken@2060
   151
            test_format = SDL_NextAudioFormat();
slouken@2060
   152
            break;
icculus@1997
   153
        }
slouken@1895
   154
    }
slouken@1895
   155
icculus@2049
   156
    format.buffer_size = _this->spec.samples;
icculus@2049
   157
slouken@2060
   158
    if (!valid_datatype) {      /* shouldn't happen, but just in case... */
icculus@2049
   159
        BEOSAUDIO_CloseDevice(_this);
icculus@2049
   160
        SDL_SetError("Unsupported audio format");
icculus@2049
   161
        return 0;
icculus@2049
   162
    }
icculus@2049
   163
icculus@2049
   164
    /* Calculate the final parameters for this audio specification */
icculus@2049
   165
    SDL_CalculateAudioSpec(&_this->spec);
icculus@2049
   166
icculus@2049
   167
    /* Subscribe to the audio stream (creates a new thread) */
icculus@2049
   168
    sigset_t omask;
icculus@2049
   169
    SDL_MaskSignals(&omask);
icculus@2049
   170
    _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
icculus@2049
   171
                                                FillSound, NULL, _this);
icculus@2049
   172
    SDL_UnmaskSignals(&omask);
icculus@2049
   173
icculus@2049
   174
    if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
icculus@2049
   175
        _this->hidden->audio_obj->SetHasData(true);
icculus@2049
   176
    } else {
icculus@2049
   177
        BEOSAUDIO_CloseDevice(_this);
icculus@2049
   178
        SDL_SetError("Unable to start Be audio");
icculus@2049
   179
        return 0;
icculus@2049
   180
    }
icculus@2049
   181
icculus@2049
   182
    /* We're running! */
icculus@2049
   183
    return 1;
icculus@2049
   184
}
icculus@2049
   185
icculus@2049
   186
static void
icculus@2049
   187
BEOSAUDIO_Deinitialize(void)
icculus@2049
   188
{
icculus@2049
   189
    SDL_QuitBeApp();
icculus@2049
   190
}
icculus@2049
   191
icculus@2049
   192
static int
slouken@2060
   193
BEOSAUDIO_Init(SDL_AudioDriverImpl * impl)
icculus@2049
   194
{
icculus@2049
   195
    /* Initialize the Be Application, if it's not already started */
icculus@2049
   196
    if (SDL_InitBeApp() < 0) {
icculus@2049
   197
        return 0;
icculus@2049
   198
    }
icculus@2049
   199
icculus@2049
   200
    /* Set the function pointers */
icculus@2049
   201
    impl->OpenDevice = BEOSAUDIO_OpenDevice;
icculus@2049
   202
    impl->CloseDevice = BEOSAUDIO_CloseDevice;
icculus@2049
   203
    impl->Deinitialize = BEOSAUDIO_Deinitialize;
icculus@2049
   204
    impl->ProvidesOwnCallbackThread = 1;
icculus@2049
   205
    impl->OnlyHasDefaultOutputDevice = 1;
icculus@2049
   206
icculus@3699
   207
    return 1;   /* this audio target is available. */
icculus@2049
   208
}
icculus@2049
   209
slouken@2060
   210
extern "C"
slouken@2060
   211
{
slouken@2060
   212
    extern AudioBootStrap BEOSAUDIO_bootstrap;
slouken@2060
   213
}
icculus@2049
   214
AudioBootStrap BEOSAUDIO_bootstrap = {
icculus@2049
   215
    "baudio", "BeOS BSoundPlayer", BEOSAUDIO_Init, 0
icculus@2049
   216
};
slouken@1895
   217
slouken@1895
   218
/* vi: set ts=4 sw=4 expandtab: */