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