146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL - Simple DirectMedia Layer 346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Copyright (C) 1997-2006 Sam Lantinga 446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is free software; you can redistribute it and/or 646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner modify it under the terms of the GNU Lesser General Public 746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License as published by the Free Software Foundation; either 846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner version 2.1 of the License, or (at your option) any later version. 946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is distributed in the hope that it will be useful, 1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner but WITHOUT ANY WARRANTY; without even the implied warranty of 1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Lesser General Public License for more details. 1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner You should have received a copy of the GNU Lesser General Public 1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License along with this library; if not, write to the Free Software 1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sam Lantinga 2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner slouken@libsdl.org 2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/ 2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h" 2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Allow access to an ESD network stream mixing buffer */ 2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/types.h> 2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <unistd.h> 2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <signal.h> 2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <errno.h> 3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <esd.h> 3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_timer.h" 3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_audio.h" 3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_audiomem.h" 3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_audio_c.h" 3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_audiodev_c.h" 3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_esdaudio.h" 3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC 4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_name.h" 4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_loadso.h" 4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define SDL_NAME(X) X 4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The tag name used by ESD audio */ 4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ESD_DRIVER_NAME "esd" 4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Audio driver functions */ 5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int ESD_OpenAudio(_THIS, SDL_AudioSpec *spec); 5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void ESD_WaitAudio(_THIS); 5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void ESD_PlayAudio(_THIS); 5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint8 *ESD_GetAudioBuf(_THIS); 5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void ESD_CloseAudio(_THIS); 5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC 5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC; 5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void *esd_handle = NULL; 6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int esd_loaded = 0; 6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int (*SDL_NAME(esd_open_sound))( const char *host ); 6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int (*SDL_NAME(esd_close))( int esd ); 6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int (*SDL_NAME(esd_play_stream))( esd_format_t format, int rate, 6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner const char *host, const char *name ); 6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic struct { 6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner const char *name; 6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner void **func; 6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} esd_functions[] = { 7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { "esd_open_sound", (void **)&SDL_NAME(esd_open_sound) }, 7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { "esd_close", (void **)&SDL_NAME(esd_close) }, 7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { "esd_play_stream", (void **)&SDL_NAME(esd_play_stream) }, 7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}; 7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void UnloadESDLibrary() 7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( esd_loaded ) { 7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_UnloadObject(esd_handle); 7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner esd_handle = NULL; 8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner esd_loaded = 0; 8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int LoadESDLibrary(void) 8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i, retval = -1; 8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner esd_handle = SDL_LoadObject(esd_library); 8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( esd_handle ) { 9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner esd_loaded = 1; 9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner retval = 0; 9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i=0; i<SDL_arraysize(esd_functions); ++i ) { 9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *esd_functions[i].func = SDL_LoadFunction(esd_handle, esd_functions[i].name); 9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( !*esd_functions[i].func ) { 9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner retval = -1; 9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner UnloadESDLibrary(); 9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return retval; 10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void UnloadESDLibrary() 10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return; 10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int LoadESDLibrary(void) 11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return 0; 11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */ 11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Audio driver bootstrap functions */ 11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Audio_Available(void) 12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int connection; 12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int available; 12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner available = 0; 12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( LoadESDLibrary() < 0 ) { 12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return available; 12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner connection = SDL_NAME(esd_open_sound)(NULL); 13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( connection >= 0 ) { 13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner available = 1; 13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_NAME(esd_close)(connection); 13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner UnloadESDLibrary(); 13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(available); 13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Audio_DeleteDevice(SDL_AudioDevice *device) 13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(device->hidden); 14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(device); 14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner UnloadESDLibrary(); 14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDL_AudioDevice *Audio_CreateDevice(int devindex) 14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_AudioDevice *this; 14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Initialize all variables that we clean on shutdown */ 15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner LoadESDLibrary(); 15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); 15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( this ) { 15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(this, 0, (sizeof *this)); 15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->hidden = (struct SDL_PrivateAudioData *) 15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_malloc((sizeof *this->hidden)); 15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (this == NULL) || (this->hidden == NULL) ) { 15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( this ) { 16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(this); 16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(0); 16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(this->hidden, 0, (sizeof *this->hidden)); 16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_fd = -1; 16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Set the function pointers */ 16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->OpenAudio = ESD_OpenAudio; 16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->WaitAudio = ESD_WaitAudio; 17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->PlayAudio = ESD_PlayAudio; 17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->GetAudioBuf = ESD_GetAudioBuf; 17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->CloseAudio = ESD_CloseAudio; 17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->free = Audio_DeleteDevice; 17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return this; 17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 17946be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerAudioBootStrap ESD_bootstrap = { 18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ESD_DRIVER_NAME, "Enlightened Sound Daemon", 18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Audio_Available, Audio_CreateDevice 18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}; 18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* This function waits until it is possible to write a full sound buffer */ 18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void ESD_WaitAudio(_THIS) 18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sint32 ticks; 18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Check to see if the thread-parent process is still alive */ 19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { static int cnt = 0; 19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Note that this only works with thread implementations 19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner that use a different process id for each thread. 19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ 19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( kill(parent, 0) < 0 ) { 19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->enabled = 0; 19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Use timer for general audio synchronization */ 20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; 20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ticks > 0 ) { 20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Delay(ticks); 20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void ESD_PlayAudio(_THIS) 20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int written; 21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Write the audio data, checking for EAGAIN on broken audio drivers */ 21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner do { 21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner written = write(audio_fd, mixbuf, mixlen); 21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) { 21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_Delay(1); /* Let a little CPU time go by */ 21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } while ( (written < 0) && 21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) ); 22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Set the next write frame */ 22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner next_frame += frame_ticks; 22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* If we couldn't write, assume fatal error for now */ 22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( written < 0 ) { 22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner this->enabled = 0; 22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint8 *ESD_GetAudioBuf(_THIS) 23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(mixbuf); 23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void ESD_CloseAudio(_THIS) 23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( mixbuf != NULL ) { 23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_FreeAudioMem(mixbuf); 23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mixbuf = NULL; 24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( audio_fd >= 0 ) { 24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_NAME(esd_close)(audio_fd); 24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_fd = -1; 24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Try to get the name of the program */ 24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic char *get_progname(void) 24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner char *progname = NULL; 25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef __LINUX__ 25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner FILE *fp; 25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner static char temp[BUFSIZ]; 25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid()); 25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fp = fopen(temp, "r"); 25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( fp != NULL ) { 25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( fgets(temp, sizeof(temp)-1, fp) ) { 25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner progname = SDL_strrchr(temp, '/'); 26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( progname == NULL ) { 26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner progname = temp; 26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner progname = progname+1; 26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner fclose(fp); 26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(progname); 27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int ESD_OpenAudio(_THIS, SDL_AudioSpec *spec) 27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner esd_format_t format; 27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Convert audio spec to the ESD audio format */ 27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format = (ESD_STREAM | ESD_PLAY); 27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch ( spec->format & 0xFF ) { 27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 8: 28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format |= ESD_BITS8; 28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case 16: 28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format |= ESD_BITS16; 28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Unsupported ESD audio format"); 28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(-1); 28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( spec->channels == 1 ) { 29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format |= ESD_MONO; 29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner format |= ESD_STEREO; 29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if 0 29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner spec->samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */ 29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Open a connection to the ESD audio server */ 29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner audio_fd = SDL_NAME(esd_play_stream)(format, spec->freq, NULL, get_progname()); 30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( audio_fd < 0 ) { 30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't open ESD connection"); 30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(-1); 30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Calculate the final parameters for this audio specification */ 30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_CalculateAudioSpec(spec); 30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner frame_ticks = (float)(spec->samples*1000)/spec->freq; 30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner next_frame = SDL_GetTicks()+frame_ticks; 30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Allocate mixing buffer */ 31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mixlen = spec->size; 31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); 31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( mixbuf == NULL ) { 31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(-1); 31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(mixbuf, spec->silence, spec->size); 31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Get the parent process id (we're the parent of the audio thread) */ 31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner parent = getpid(); 32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* We're ready to rock and roll. :-) */ 32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(0); 32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 324