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__