src/audio/haiku/SDL_haikuaudio.cc
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Feb 2014 00:53:27 -0800
changeset 8149 681eb46b8ac4
parent 8093 b43765095a6f
child 9394 bb28e5281770
permissions -rw-r--r--
Fixed bug 2374 - Update copyright for 2014...

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