src/audio/baudio/SDL_beaudio.cc
author Ryan C. Gordon <icculus@icculus.org>
Sun, 08 Oct 2006 01:39:01 +0000
branchSDL-ryan-multiple-audio-device
changeset 3837 7c9663fb0860
parent 3830 29e83f221c62
child 3846 66fb40445587
permissions -rw-r--r--
BeOS audio now works in 1.3 branch.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 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@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 
    33 #include "SDL_audio.h"
    34 #include "../SDL_audio_c.h"
    35 #include "../SDL_sysaudio.h"
    36 #include "../../thread/beos/SDL_systhread_c.h"
    37 #include "SDL_beaudio.h"
    38 
    39 }
    40 
    41 
    42 static int BEOSAUDIO_Available(void)
    43 {
    44     return 1;  /* Always available on BeOS. */
    45 }
    46 
    47 
    48 /* !!! FIXME: have the callback call the higher level to avoid code dupe. */
    49 /* The BeOS callback for handling the audio buffer */
    50 static void
    51 FillSound(void *device, void *stream, size_t len,
    52           const media_raw_audio_format & format)
    53 {
    54     SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
    55 
    56     /* Silence the buffer, since it's ours */
    57     SDL_memset(stream, audio->spec.silence, len);
    58 
    59     /* Only do soemthing if audio is enabled */
    60     if (!audio->enabled)
    61         return;
    62 
    63     if (!audio->paused) {
    64         if (audio->convert.needed) {
    65             SDL_mutexP(audio->mixer_lock);
    66             (*audio->spec.callback) (audio->spec.userdata,
    67                                          (Uint8 *) audio->convert.buf,
    68                                          audio->convert.len);
    69             SDL_mutexV(audio->mixer_lock);
    70             SDL_ConvertAudio(&audio->convert);
    71             SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
    72         } else {
    73             SDL_mutexP(audio->mixer_lock);
    74             (*audio->spec.callback) (audio->spec.userdata,
    75                                         (Uint8 *) stream, len);
    76             SDL_mutexV(audio->mixer_lock);
    77         }
    78     }
    79 }
    80 
    81 static void
    82 BEOSAUDIO_CloseDevice(_THIS)
    83 {
    84     if (_this->hidden != NULL) {
    85         if (_this->hidden->audio_obj) {
    86             _this->hidden->audio_obj->Stop();
    87             delete _this->hidden->audio_obj;
    88             _this->hidden->audio_obj = NULL;
    89         }
    90 
    91         delete _this->hidden;
    92         _this->hidden = NULL;
    93     }
    94 }
    95 
    96 static int
    97 BEOSAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
    98 {
    99     int valid_datatype = 0;
   100     media_raw_audio_format format;
   101     SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
   102 
   103     /* Initialize all variables that we clean on shutdown */
   104     _this->hidden = new SDL_PrivateAudioData;
   105     if (_this->hidden == NULL) {
   106         SDL_OutOfMemory();
   107         return 0;
   108     }
   109     SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
   110 
   111     /* Parse the audio format and fill the Be raw audio format */
   112     SDL_memset(&format, '\0', sizeof(media_raw_audio_format));
   113     format.byte_order = B_MEDIA_LITTLE_ENDIAN;
   114     format.frame_rate = (float) _this->spec.freq;
   115     format.channel_count = _this->spec.channels;  /* !!! FIXME: support > 2? */
   116     while ((!valid_datatype) && (test_format)) {
   117         valid_datatype = 1;
   118         _this->spec.format = test_format;
   119         switch (test_format) {
   120             case AUDIO_S8:
   121                 format.format = media_raw_audio_format::B_AUDIO_CHAR;
   122                 break;
   123 
   124             case AUDIO_U8:
   125                 format.format = media_raw_audio_format::B_AUDIO_UCHAR;
   126                 break;
   127 
   128             case AUDIO_S16LSB:
   129                 format.format = media_raw_audio_format::B_AUDIO_SHORT;
   130                 break;
   131 
   132             case AUDIO_S16MSB:
   133                 format.format = media_raw_audio_format::B_AUDIO_SHORT;
   134                 format.byte_order = B_MEDIA_BIG_ENDIAN;
   135                 break;
   136 
   137             case AUDIO_S32LSB:
   138                 format.format = media_raw_audio_format::B_AUDIO_INT;
   139                 break;
   140 
   141             case AUDIO_S32MSB:
   142                 format.format = media_raw_audio_format::B_AUDIO_INT;
   143                 format.byte_order = B_MEDIA_BIG_ENDIAN;
   144                 break;
   145 
   146             case AUDIO_F32LSB:
   147                 format.format = media_raw_audio_format::B_AUDIO_FLOAT;
   148                 break;
   149 
   150             case AUDIO_F32MSB:
   151                 format.format = media_raw_audio_format::B_AUDIO_FLOAT;
   152                 format.byte_order = B_MEDIA_BIG_ENDIAN;
   153                 break;
   154 
   155             default:
   156                 valid_datatype = 0;
   157                 test_format = SDL_NextAudioFormat();
   158                 break;
   159         }
   160     }
   161 
   162     format.buffer_size = _this->spec.samples;
   163 
   164     if (!valid_datatype) {  /* shouldn't happen, but just in case... */
   165         BEOSAUDIO_CloseDevice(_this);
   166         SDL_SetError("Unsupported audio format");
   167         return 0;
   168     }
   169 
   170     /* Calculate the final parameters for this audio specification */
   171     SDL_CalculateAudioSpec(&_this->spec);
   172 
   173     /* Subscribe to the audio stream (creates a new thread) */
   174     sigset_t omask;
   175     SDL_MaskSignals(&omask);
   176     _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
   177                                                 FillSound, NULL, _this);
   178     SDL_UnmaskSignals(&omask);
   179 
   180     if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
   181         _this->hidden->audio_obj->SetHasData(true);
   182     } else {
   183         BEOSAUDIO_CloseDevice(_this);
   184         SDL_SetError("Unable to start Be audio");
   185         return 0;
   186     }
   187 
   188     /* We're running! */
   189     return 1;
   190 }
   191 
   192 static void
   193 BEOSAUDIO_Deinitialize(void)
   194 {
   195     SDL_QuitBeApp();
   196 }
   197 
   198 static int
   199 BEOSAUDIO_Init(SDL_AudioDriverImpl *impl)
   200 {
   201     /* Initialize the Be Application, if it's not already started */
   202     if (SDL_InitBeApp() < 0) {
   203         return 0;
   204     }
   205 
   206     /* Set the function pointers */
   207     impl->OpenDevice = BEOSAUDIO_OpenDevice;
   208     impl->CloseDevice = BEOSAUDIO_CloseDevice;
   209     impl->Deinitialize = BEOSAUDIO_Deinitialize;
   210     impl->ProvidesOwnCallbackThread = 1;
   211     impl->OnlyHasDefaultOutputDevice = 1;
   212 
   213     return 1;
   214 }
   215 
   216 extern "C" { extern AudioBootStrap BEOSAUDIO_bootstrap; }
   217 AudioBootStrap BEOSAUDIO_bootstrap = {
   218     "baudio", "BeOS BSoundPlayer",
   219     BEOSAUDIO_Available, BEOSAUDIO_Init, 0
   220 };
   221 
   222 /* vi: set ts=4 sw=4 expandtab: */
   223