Home | History | Annotate | Download | only in baudio
      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