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