sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_haikuaudio.cc (7231B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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_internal.h"
     22 
     23 #if SDL_AUDIO_DRIVER_HAIKU
     24 
     25 /* Allow access to the audio stream on Haiku */
     26 
     27 #include <SoundPlayer.h>
     28 #include <signal.h>
     29 
     30 #include "../../main/haiku/SDL_BeApp.h"
     31 
     32 extern "C"
     33 {
     34 
     35 #include "SDL_audio.h"
     36 #include "../SDL_audio_c.h"
     37 #include "../SDL_sysaudio.h"
     38 #include "SDL_haikuaudio.h"
     39 
     40 }
     41 
     42 
     43 /* !!! FIXME: have the callback call the higher level to avoid code dupe. */
     44 /* The Haiku callback for handling the audio buffer */
     45 static void
     46 FillSound(void *device, void *stream, size_t len,
     47           const media_raw_audio_format & format)
     48 {
     49     SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
     50     SDL_AudioCallback callback = audio->callbackspec.callback;
     51 
     52     /* Only do something if audio is enabled */
     53     if (!SDL_AtomicGet(&audio->enabled) || SDL_AtomicGet(&audio->paused)) {
     54         if (audio->stream) {
     55             SDL_AudioStreamClear(audio->stream);
     56         }
     57         SDL_memset(stream, audio->spec.silence, len);
     58         return;
     59     }
     60 
     61     SDL_assert(audio->spec.size == len);
     62 
     63     if (audio->stream == NULL) {  /* no conversion necessary. */
     64         SDL_LockMutex(audio->mixer_lock);
     65         callback(audio->callbackspec.userdata, (Uint8 *) stream, len);
     66         SDL_UnlockMutex(audio->mixer_lock);
     67     } else {  /* streaming/converting */
     68         const int stream_len = audio->callbackspec.size;
     69         const int ilen = (int) len;
     70         while (SDL_AudioStreamAvailable(audio->stream) < ilen) {
     71             callback(audio->callbackspec.userdata, audio->work_buffer, stream_len);
     72             if (SDL_AudioStreamPut(audio->stream, audio->work_buffer, stream_len) == -1) {
     73                 SDL_AudioStreamClear(audio->stream);
     74                 SDL_AtomicSet(&audio->enabled, 0);
     75                 break;
     76             }
     77         }
     78 
     79         const int got = SDL_AudioStreamGet(audio->stream, stream, ilen);
     80         SDL_assert((got < 0) || (got == ilen));
     81         if (got != ilen) {
     82             SDL_memset(stream, audio->spec.silence, len);
     83         }
     84     }
     85 }
     86 
     87 static void
     88 HAIKUAUDIO_CloseDevice(_THIS)
     89 {
     90     if (_this->hidden->audio_obj) {
     91         _this->hidden->audio_obj->Stop();
     92         delete _this->hidden->audio_obj;
     93     }
     94     delete _this->hidden;
     95 }
     96 
     97 
     98 static const int sig_list[] = {
     99     SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0
    100 };
    101 
    102 static inline void
    103 MaskSignals(sigset_t * omask)
    104 {
    105     sigset_t mask;
    106     int i;
    107 
    108     sigemptyset(&mask);
    109     for (i = 0; sig_list[i]; ++i) {
    110         sigaddset(&mask, sig_list[i]);
    111     }
    112     sigprocmask(SIG_BLOCK, &mask, omask);
    113 }
    114 
    115 static inline void
    116 UnmaskSignals(sigset_t * omask)
    117 {
    118     sigprocmask(SIG_SETMASK, omask, NULL);
    119 }
    120 
    121 
    122 static int
    123 HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    124 {
    125     int valid_datatype = 0;
    126     media_raw_audio_format format;
    127     SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
    128 
    129     /* Initialize all variables that we clean on shutdown */
    130     _this->hidden = new SDL_PrivateAudioData;
    131     if (_this->hidden == NULL) {
    132         return SDL_OutOfMemory();
    133     }
    134     SDL_zerop(_this->hidden);
    135 
    136     /* Parse the audio format and fill the Be raw audio format */
    137     SDL_zero(format);
    138     format.byte_order = B_MEDIA_LITTLE_ENDIAN;
    139     format.frame_rate = (float) _this->spec.freq;
    140     format.channel_count = _this->spec.channels;        /* !!! FIXME: support > 2? */
    141     while ((!valid_datatype) && (test_format)) {
    142         valid_datatype = 1;
    143         _this->spec.format = test_format;
    144         switch (test_format) {
    145         case AUDIO_S8:
    146             format.format = media_raw_audio_format::B_AUDIO_CHAR;
    147             break;
    148 
    149         case AUDIO_U8:
    150             format.format = media_raw_audio_format::B_AUDIO_UCHAR;
    151             break;
    152 
    153         case AUDIO_S16LSB:
    154             format.format = media_raw_audio_format::B_AUDIO_SHORT;
    155             break;
    156 
    157         case AUDIO_S16MSB:
    158             format.format = media_raw_audio_format::B_AUDIO_SHORT;
    159             format.byte_order = B_MEDIA_BIG_ENDIAN;
    160             break;
    161 
    162         case AUDIO_S32LSB:
    163             format.format = media_raw_audio_format::B_AUDIO_INT;
    164             break;
    165 
    166         case AUDIO_S32MSB:
    167             format.format = media_raw_audio_format::B_AUDIO_INT;
    168             format.byte_order = B_MEDIA_BIG_ENDIAN;
    169             break;
    170 
    171         case AUDIO_F32LSB:
    172             format.format = media_raw_audio_format::B_AUDIO_FLOAT;
    173             break;
    174 
    175         case AUDIO_F32MSB:
    176             format.format = media_raw_audio_format::B_AUDIO_FLOAT;
    177             format.byte_order = B_MEDIA_BIG_ENDIAN;
    178             break;
    179 
    180         default:
    181             valid_datatype = 0;
    182             test_format = SDL_NextAudioFormat();
    183             break;
    184         }
    185     }
    186 
    187     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
    188         return SDL_SetError("Unsupported audio format");
    189     }
    190 
    191     /* Calculate the final parameters for this audio specification */
    192     SDL_CalculateAudioSpec(&_this->spec);
    193 
    194     format.buffer_size = _this->spec.size;
    195 
    196     /* Subscribe to the audio stream (creates a new thread) */
    197     sigset_t omask;
    198     MaskSignals(&omask);
    199     _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
    200                                                 FillSound, NULL, _this);
    201     UnmaskSignals(&omask);
    202 
    203     if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
    204         _this->hidden->audio_obj->SetHasData(true);
    205     } else {
    206         return SDL_SetError("Unable to start Be audio");
    207     }
    208 
    209     /* We're running! */
    210     return 0;
    211 }
    212 
    213 static void
    214 HAIKUAUDIO_Deinitialize(void)
    215 {
    216     SDL_QuitBeApp();
    217 }
    218 
    219 static int
    220 HAIKUAUDIO_Init(SDL_AudioDriverImpl * impl)
    221 {
    222     /* Initialize the Be Application, if it's not already started */
    223     if (SDL_InitBeApp() < 0) {
    224         return 0;
    225     }
    226 
    227     /* Set the function pointers */
    228     impl->OpenDevice = HAIKUAUDIO_OpenDevice;
    229     impl->CloseDevice = HAIKUAUDIO_CloseDevice;
    230     impl->Deinitialize = HAIKUAUDIO_Deinitialize;
    231     impl->ProvidesOwnCallbackThread = 1;
    232     impl->OnlyHasDefaultOutputDevice = 1;
    233 
    234     return 1;   /* this audio target is available. */
    235 }
    236 
    237 extern "C"
    238 {
    239     extern AudioBootStrap HAIKUAUDIO_bootstrap;
    240 }
    241 AudioBootStrap HAIKUAUDIO_bootstrap = {
    242     "haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, 0
    243 };
    244 
    245 #endif /* SDL_AUDIO_DRIVER_HAIKU */
    246 
    247 /* vi: set ts=4 sw=4 expandtab: */