SDL_haikuaudio.cc (6937B)
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 32extern "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 */ 45static void 46FillSound(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 73static void 74HAIKUAUDIO_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 89static const int sig_list[] = { 90 SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0 91}; 92 93static inline void 94MaskSignals(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 106static inline void 107UnmaskSignals(sigset_t * omask) 108{ 109 sigprocmask(SIG_SETMASK, omask, NULL); 110} 111 112 113static int 114HAIKUAUDIO_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 206static void 207HAIKUAUDIO_Deinitialize(void) 208{ 209 SDL_QuitBeApp(); 210} 211 212static int 213HAIKUAUDIO_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 230extern "C" 231{ 232 extern AudioBootStrap HAIKUAUDIO_bootstrap; 233} 234AudioBootStrap 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: */