diff --git a/src/xpdev/xpbeep.c b/src/xpdev/xpbeep.c index 778d43ef2ceff07d1a3ab36cda9103fb49a78431..e98b4750ae46105ce8346dfe2b519fb61b71bae8 100644 --- a/src/xpdev/xpbeep.c +++ b/src/xpdev/xpbeep.c @@ -51,6 +51,27 @@ static BOOL sound_device_open_failed=FALSE; static BOOL alsa_device_open_failed=FALSE; +enum { + SOUND_DEVICE_CLOSED + ,SOUND_DEVICE_WIN32 + ,SOUND_DEVICE_ALSA + ,SOUND_DEVICE_OSS +}; + +static int handle_type=SOUND_DEVICE_CLOSED; + +#ifdef _WIN32 +static HWAVEOUT waveOut; +#endif + +#ifdef USE_ALSA_SOUND +static snd_pcm_t *playback_handle; +#endif + +#ifdef AFMT_U8 +static int dsp; +#endif + #define WAVE_PI 3.14159265358979323846 #define WAVE_TPI 6.28318530717958647692 @@ -174,22 +195,25 @@ void makewave(double freq, unsigned char *wave, int samples, enum WAVE_SHAPE sha #endif } -/********************************************************************************/ -/* Play a tone through the wave/DSP output device (sound card) - Deuce */ -/********************************************************************************/ - -#if defined(_WIN32) - -BOOL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) +BOOL xptone_open(void) { +#ifdef _WIN32 WAVEFORMATEX w; - WAVEHDR wh; - HWAVEOUT waveOut; - unsigned char wave[S_RATE*15/2+1]; - WORD* p; - DWORD endTime; - BOOL success=FALSE; +#endif +#ifdef AFMT_U8 + int format=AFMT_U8; + int channels=1; + int rate=S_RATE; + int fragsize=0x7fff0004; +#endif + +fprintf(stderr,"1\n"); + /* Already open */ + if(handle_type!=SOUND_DEVICE_CLOSED) + return(TRUE); + +#ifdef _WIN32 w.wFormatTag = WAVE_FORMAT_PCM; w.nChannels = 1; w.nSamplesPerSec = S_RATE; @@ -201,64 +225,14 @@ BOOL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) sound_device_open_failed=TRUE; if(sound_device_open_failed) return(FALSE); - - memset(&wh, 0, sizeof(wh)); - wh.lpData=wave; - wh.dwBufferLength=S_RATE*duration/1000; - if(wh.dwBufferLength<=S_RATE/freq*2) - wh.dwBufferLength=S_RATE/freq*2; - - makewave(freq,wave,wh.dwBufferLength,shape); - if(waveOutPrepareHeader(waveOut, &wh, sizeof(wh))!=MMSYSERR_NOERROR) - goto abrt; - if(waveOutWrite(waveOut, &wh, sizeof(wh))==MMSYSERR_NOERROR) - success=TRUE; -abrt: - while(waveOutUnprepareHeader(waveOut, &wh, sizeof(wh))==WAVERR_STILLPLAYING) - SLEEP(1); - waveOutClose(waveOut); - - return(success); -} - -#elif defined(__unix__) - -BOOL DLLCALL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) -{ -#if defined(USE_ALSA_SOUND) || defined(AFMT_U8) - unsigned char wave[S_RATE*15/2+1]; - int samples; -#endif - -#ifdef USE_ALSA_SOUND - snd_pcm_t *playback_handle; - snd_pcm_hw_params_t *hw_params=NULL; - void *dl; -#endif - -#ifdef AFMT_U8 - int dsp; - int format=AFMT_U8; - int channels=1; - int rate=S_RATE; - int fragsize=0x7fff0004; - int wr; - int i; -#endif - -#if defined(USE_ALSA_SOUND) || defined(AFMT_U8) - if(freq<17) - freq=17; - samples=S_RATE*duration/1000; - if(samples<=S_RATE/freq*2) - samples=S_RATE/freq*2; - makewave(freq,wave,samples,shape); + handle_type=SOUND_DEVICE_WIN32; + if(!sound_device_open_failed)) + return(TRUE); #endif #ifdef USE_ALSA_SOUND if(!alsa_device_open_failed) { if(alsa_api==NULL) { - if(((alsa_api=(struct alsa_api_struct *)malloc(sizeof(struct alsa_api_struct)))==NULL) || ((dl=dlopen("libasound.so",RTLD_LAZY))==NULL) || ((alsa_api->snd_pcm_open=dlsym(dl,"snd_pcm_open"))==NULL) @@ -274,12 +248,10 @@ BOOL DLLCALL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) || ((alsa_api->snd_pcm_close=dlsym(dl,"snd_pcm_close"))==NULL) || ((alsa_api->snd_pcm_writei=dlsym(dl,"snd_pcm_writei"))==NULL) || ((alsa_api->=dlsym(dl,""))==NULL)) { - FREE_AND_NULL(alsa_api); + alsa_device_open_failed=TRUE; } if(alsa_api==NULL) alsa_device_open_failed=TRUE; - else { - } } if(alsa_api!=NULL) { if((alsa_api->snd_pcm_open(&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)<0) @@ -294,22 +266,16 @@ BOOL DLLCALL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) alsa_device_open_failed=TRUE; if(hw_params!=NULL) alsa_api->snd_pcm_hw_params_free(hw_params); - if(playback_handle!=NULL) + if(playback_handle!=NULL) { alsa_api->snd_pcm_close(playback_handle); + playback_handle=NULL; + } } else { - alsa_api->snd_pcm_hw_params_free(hw_params); - if(alsa_api->snd_pcm_writei(playback_handle, wave, samples)!=samples) - alsa_device_open_failed=TRUE; - else { - alsa_api->snd_pcm_close (playback_handle); - return(TRUE); - } - alsa_api->snd_pcm_close (playback_handle); + handle_type=SOUND_DEVICE_ALSA; + return(TRUE); } } - if(alsa_device_open_failed) - FREE_AND_NULL(alsa_api); } #endif @@ -336,18 +302,144 @@ BOOL DLLCALL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) } if(sound_device_open_failed) return(FALSE); - wr=0; - while(wr<samples) { - i=write(dsp, wave+wr, samples-wr); - if(i>=0) - wr+=i; + handle_type=SOUND_DEVICE_OSS; + if(!sound_device_open_failed) + return(TRUE); +#endif + return(FALSE); +} + +BOOL xptone_close(void) +{ +#ifdef _WIN32 + if(handle_type==SOUND_DEVICE_WIN32) + waveOutClose(waveOut); +#endif + +#ifdef USE_ALSA_SOUND + if(handle_type==SOUND_DEVICE_ALSA) + alsa_api->snd_pcm_close (playback_handle); +#endif + +#ifdef AFMT_U8 + if(handle_type==SOUND_DEVICE_OSS) + close(dsp); +#endif + handle_type=SOUND_DEVICE_CLOSED; + sound_device_open_failed=FALSE; + alsa_device_open_failed=FALSE; +} + +/********************************************************************************/ +/* Play a tone through the wave/DSP output device (sound card) - Deuce */ +/********************************************************************************/ + +#if defined(_WIN32) + +BOOL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) +{ + WAVEHDR wh; + unsigned char wave[S_RATE*15/2+1]; + WORD* p; + DWORD endTime; + BOOL success=FALSE; + BOOL must_close=FALSE; + + if(handle_type==SOUND_DEVICE_CLOSED) { + must_close=TRUE; + xptone_open(); } - close(dsp); - return(TRUE); -#else - return(FALSE); + memset(&wh, 0, sizeof(wh)); + wh.lpData=wave; + wh.dwBufferLength=S_RATE*duration/1000; + if(wh.dwBufferLength<=S_RATE/freq*2) + wh.dwBufferLength=S_RATE/freq*2; + + makewave(freq,wave,wh.dwBufferLength,shape); + if(waveOutPrepareHeader(waveOut, &wh, sizeof(wh))!=MMSYSERR_NOERROR) + goto abrt; + if(waveOutWrite(waveOut, &wh, sizeof(wh))==MMSYSERR_NOERROR) + success=TRUE; +abrt: + while(waveOutUnprepareHeader(waveOut, &wh, sizeof(wh))==WAVERR_STILLPLAYING) + SLEEP(1); + + if(must_close) + xptone_close(); + + return(success); +} + +#elif defined(__unix__) + +BOOL DLLCALL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) +{ + BOOL must_close=FALSE; + +#if defined(USE_ALSA_SOUND) || defined(AFMT_U8) + unsigned char wave[S_RATE*15/2+1]; + int samples; +#endif + +#ifdef USE_ALSA_SOUND + snd_pcm_hw_params_t *hw_params=NULL; + void *dl; +#endif + +#ifdef AFMT_U8 + int wr; + int i; +#endif + + if(handle_type==SOUND_DEVICE_CLOSED) { + must_close=TRUE; + if(!xptone_open()) + return(FALSE); + } + +#if defined(USE_ALSA_SOUND) || defined(AFMT_U8) + if(freq<17) + freq=17; + samples=S_RATE*duration/1000; + if(samples<=S_RATE/freq*2) + samples=S_RATE/freq*2; + makewave(freq,wave,samples,shape); +#endif + +#ifdef USE_ALSA_SOUND + if(handle_type==SOUND_DEVICE_ALSA) { + alsa_api->snd_pcm_hw_params_free(hw_params); + if(alsa_api->snd_pcm_writei(handle, wave, samples)!=samples) { + /* Go back and try OSS */ + alsa_device_open_failed=TRUE; + alsa_api->snd_pcm_close (handle); + xptone_open(); + } + else { + if(must_close) + xptone_close(); + return(TRUE); + } + } #endif + +#ifdef AFMT_U8 + if(handle_type==SOUND_DEVICE_OSS) { + wr=0; + while(wr<samples) { + i=write(dsp, wave+wr, samples-wr); + if(i>=0) + wr+=i; + } + if(must_close) + xptone_close(); + return(TRUE); + } +#endif + if(must_close) + xptone_close(); + return(FALSE); } /****************************************************************************/ diff --git a/src/xpdev/xpbeep.h b/src/xpdev/xpbeep.h index d20ea7a1e15d31dfae34fab35123e4910146346b..57b9e720d4d24cbf10047c443faeace9c294e211 100644 --- a/src/xpdev/xpbeep.h +++ b/src/xpdev/xpbeep.h @@ -33,6 +33,8 @@ enum WAVE_SHAPE { #ifdef __cplusplus extern "C" { #endif +BOOL xptone_open(void); +BOOL xptone_close(void); void xpbeep(double freq, DWORD duration); BOOL xptone(double freq, DWORD duration, enum WAVE_SHAPE); #ifdef __unix__