diff --git a/audio/alsa.c b/audio/alsa.c index 1f5052221c..75a8b51f7b 100644 --- a/audio/alsa.c +++ b/audio/alsa.c @@ -202,18 +202,27 @@ static ssize_t alsa_write(void *data, const void *buf_, size_t size_) return written; } +static bool alsa_alive(void *data) +{ + alsa_t *alsa = (alsa_t*)data; + if (alsa) + return !alsa->is_paused; + return false; +} + static bool alsa_stop(void *data) { alsa_t *alsa = (alsa_t*)data; - if (alsa->can_pause && !alsa->is_paused) + if (alsa->can_pause + && !alsa->is_paused) { - if (snd_pcm_pause(alsa->pcm, 1) == 0) - { - alsa->is_paused = true; - return true; - } - return false; + int ret = snd_pcm_pause(alsa->pcm, 1); + + if (ret < 0) + return false; + + alsa->is_paused = true; } return true; @@ -228,20 +237,20 @@ static void alsa_set_nonblock_state(void *data, bool state) static bool alsa_start(void *data) { alsa_t *alsa = (alsa_t*)data; - if (alsa->can_pause && alsa->is_paused) + + if (alsa->can_pause + && alsa->is_paused) { int ret = snd_pcm_pause(alsa->pcm, 0); + if (ret < 0) { RARCH_ERR("[ALSA]: Failed to unpause: %s.\n", snd_strerror(ret)); return false; } - else - { - alsa->is_paused = false; - return true; - } + + alsa->is_paused = false; } return true; } @@ -289,6 +298,7 @@ audio_driver_t audio_alsa = { alsa_write, alsa_stop, alsa_start, + alsa_alive, alsa_set_nonblock_state, alsa_free, alsa_use_float, diff --git a/audio/alsa_qsa.c b/audio/alsa_qsa.c index 73bceff718..6759cd77e9 100644 --- a/audio/alsa_qsa.c +++ b/audio/alsa_qsa.c @@ -273,12 +273,40 @@ static bool alsa_qsa_stop(void *data) if (alsa->can_pause && !alsa->is_paused) { - if (snd_pcm_playback_pause(alsa->pcm) == 0) + int ret = snd_pcm_playback_pause(alsa->pcm); + if (ret < 0) + return false; + + alsa->is_paused = true; + } + + return true; +} + +static bool alsa_qsa_alive(void *data) +{ + alsa_t *alsa = (alsa_t*)data; + if (alsa) + return !alsa->is_paused; + return false; +} + +static bool alsa_qsa_start(void *data) +{ + alsa_t *alsa = (alsa_t*)data; + + if (alsa->can_pause && alsa->is_paused) + { + int ret = snd_pcm_playback_resume(alsa->pcm); + + if (ret < 0) { - alsa->is_paused = true; - return true; + RARCH_ERR("[ALSA QSA]: Failed to unpause: %s.\n", + snd_strerror(ret)); + return false; } - return false; + + alsa->is_paused = false; } return true; @@ -300,28 +328,6 @@ static void alsa_qsa_set_nonblock_state(void *data, bool state) alsa->nonblock = state; } -static bool alsa_qsa_start(void *data) -{ - alsa_t *alsa = (alsa_t*)data; - - if (alsa->can_pause && alsa->is_paused) - { - int ret = snd_pcm_playback_resume(alsa->pcm); - if (ret < 0) - { - RARCH_ERR("[ALSA QSA]: Failed to unpause: %s.\n", - snd_strerror(ret)); - return false; - } - else - { - alsa->is_paused = false; - return true; - } - } - - return true; -} static bool alsa_qsa_use_float(void *data) { @@ -366,6 +372,7 @@ audio_driver_t audio_alsa = { alsa_qsa_write, alsa_qsa_stop, alsa_qsa_start, + alsa_qsa_alive, alsa_qsa_set_nonblock_state, alsa_qsa_free, alsa_qsa_use_float, diff --git a/audio/alsathread.c b/audio/alsathread.c index 1c6bc11cb6..a0a92c4507 100644 --- a/audio/alsathread.c +++ b/audio/alsathread.c @@ -30,6 +30,7 @@ typedef struct alsa_thread { snd_pcm_t *pcm; bool nonblock; + bool is_paused; bool has_float; volatile bool thread_dead; @@ -280,9 +281,20 @@ static ssize_t alsa_thread_write(void *data, const void *buf, size_t size) } } +static bool alsa_thread_alive(void *data) +{ + alsa_thread_t *alsa = (alsa_thread_t*)data; + if (alsa) + return !alsa->is_paused; + return false; +} + static bool alsa_thread_stop(void *data) { - (void)data; + alsa_thread_t *alsa = (alsa_thread_t*)data; + + if (alsa) + alsa->is_paused = true; return true; } @@ -294,7 +306,10 @@ static void alsa_thread_set_nonblock_state(void *data, bool state) static bool alsa_thread_start(void *data) { - (void)data; + alsa_thread_t *alsa = (alsa_thread_t*)data; + + if (alsa) + alsa->is_paused = false; return true; } @@ -321,6 +336,7 @@ audio_driver_t audio_alsathread = { alsa_thread_write, alsa_thread_stop, alsa_thread_start, + alsa_thread_alive, alsa_thread_set_nonblock_state, alsa_thread_free, alsa_thread_use_float, diff --git a/audio/coreaudio.c b/audio/coreaudio.c index d9f3a43bc9..1a71bfde27 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -43,6 +43,7 @@ typedef struct coreaudio AudioComponentInstance dev; #endif bool dev_alive; + bool is_paused; fifo_buffer_t *buffer; bool nonblock; @@ -363,22 +364,32 @@ static ssize_t coreaudio_write(void *data, const void *buf_, size_t size) return written; } -static bool coreaudio_stop(void *data) -{ - coreaudio_t *dev = (coreaudio_t*)data; - return AudioOutputUnitStop(dev->dev) == noErr; -} - static void coreaudio_set_nonblock_state(void *data, bool state) { coreaudio_t *dev = (coreaudio_t*)data; dev->nonblock = state; } +static bool coreaudio_alive(void *data) +{ + coreaudio_t *dev = (coreaudio_t*)data; + if (dev) + return !dev->is_paused; + return false; +} + +static bool coreaudio_stop(void *data) +{ + coreaudio_t *dev = (coreaudio_t*)data; + dev->is_paused = (AudioOutputUnitStop(dev->dev) == noErr) ? true : false; + return dev->is_paused ? true : false; +} + static bool coreaudio_start(void *data) { coreaudio_t *dev = (coreaudio_t*)data; - return AudioOutputUnitStart(dev->dev) == noErr; + dev->is_paused = (AudioOutputUnitStart(dev->dev) == noErr) ? false : true; + return dev->is_paused ? false : true; } static bool coreaudio_use_float(void *data) @@ -407,6 +418,7 @@ audio_driver_t audio_coreaudio = { coreaudio_write, coreaudio_stop, coreaudio_start, + coreaudio_alive, coreaudio_set_nonblock_state, coreaudio_free, coreaudio_use_float, diff --git a/audio/dsound.c b/audio/dsound.c index 7c757b7e2e..f886d89cfe 100644 --- a/audio/dsound.c +++ b/audio/dsound.c @@ -69,6 +69,7 @@ typedef struct dsound unsigned buffer_size; bool nonblock; + bool is_paused; volatile bool thread_alive; } dsound_t; @@ -384,7 +385,8 @@ static bool dsound_stop(void *data) { dsound_t *ds = (dsound_t*)data; dsound_stop_thread(ds); - return IDirectSoundBuffer_Stop(ds->dsb) == DS_OK; + ds->is_paused = (IDirectSoundBuffer_Stop(ds->dsb) == DS_OK) ? true : false; + return (ds->is_paused) ? true : false; } static bool dsound_start(void *data) @@ -395,7 +397,16 @@ static bool dsound_start(void *data) if (!dsound_start_thread(ds)) return false; - return IDirectSoundBuffer_Play(ds->dsb, 0, 0, DSBPLAY_LOOPING) == DS_OK; + ds->is_paused = (IDirectSoundBuffer_Play(ds->dsb, 0, 0, DSBPLAY_LOOPING) == DS_OK) ? false : true; + return (ds->is_paused) ? false : true; +} + +static bool dsound_alive(void *data) +{ + dsound_t *ds = (dsound_t*)data; + if (ds) + return !ds->is_paused; + return false; } static void dsound_set_nonblock_state(void *data, bool state) @@ -462,6 +473,7 @@ audio_driver_t audio_dsound = { dsound_write, dsound_stop, dsound_start, + dsound_alive, dsound_set_nonblock_state, dsound_free, dsound_use_float, diff --git a/audio/gx_audio.c b/audio/gx_audio.c index d2d2b3f4b8..b268d8c966 100644 --- a/audio/gx_audio.c +++ b/audio/gx_audio.c @@ -53,6 +53,7 @@ typedef struct OSCond cond; bool nonblock; + bool is_paused; } gx_audio_t; static volatile gx_audio_t *gx_audio_data; @@ -163,6 +164,7 @@ static bool gx_audio_stop(void *data) AIStopDMA(); memset(wa->data, 0, sizeof(wa->data)); DCFlushRange(wa->data, sizeof(wa->data)); + wa->is_paused = true; return true; } @@ -178,11 +180,20 @@ static void gx_audio_set_nonblock_state(void *data, bool state) static bool gx_audio_start(void *data) { - (void)data; + gx_audio_t *wa = (gx_audio_t*)data; AIStartDMA(); + wa->is_paused = false; return true; } +static bool gx_audio_alive(void *data) +{ + gx_audio_t *wa = (gx_audio_t*)data; + if (wa) + return !wa->is_paused; + return false; +} + static void gx_audio_free(void *data) { gx_audio_t *wa = (gx_audio_t*)data; @@ -225,6 +236,7 @@ audio_driver_t audio_gx = { gx_audio_write, gx_audio_stop, gx_audio_start, + gx_audio_alive, gx_audio_set_nonblock_state, gx_audio_free, gx_audio_use_float, diff --git a/audio/jack.c b/audio/jack.c index 059e358c47..9b740d950a 100644 --- a/audio/jack.c +++ b/audio/jack.c @@ -36,6 +36,7 @@ typedef struct jack jack_ringbuffer_t *buffer[2]; volatile bool shutdown; bool nonblock; + bool is_paused; pthread_cond_t cond; pthread_mutex_t cond_lock; @@ -274,10 +275,20 @@ static ssize_t ja_write(void *data, const void *buf, size_t size) static bool ja_stop(void *data) { - (void)data; + jack_t *jd = (jack_t*)data; + if (jd) + jd->is_paused = true; return true; } +static bool ja_alive(void *data) +{ + jack_t *jd = (jack_t*)data; + if (jd) + return !jd->is_paused; + return false; +} + static void ja_set_nonblock_state(void *data, bool state) { jack_t *jd = (jack_t*)data; @@ -286,7 +297,9 @@ static void ja_set_nonblock_state(void *data, bool state) static bool ja_start(void *data) { - (void)data; + jack_t *jd = (jack_t*)data; + if (jd) + jd->is_paused = false; return true; } @@ -335,6 +348,7 @@ audio_driver_t audio_jack = { ja_write, ja_stop, ja_start, + ja_alive, ja_set_nonblock_state, ja_free, ja_use_float, diff --git a/audio/nullaudio.c b/audio/nullaudio.c index 18b55872e3..5ead09c472 100644 --- a/audio/nullaudio.c +++ b/audio/nullaudio.c @@ -43,6 +43,12 @@ static bool null_audio_stop(void *data) return true; } +static bool null_audio_alive(void *data) +{ + (void)data; + return true; +} + static bool null_audio_start(void *data) { (void)data; @@ -66,6 +72,7 @@ audio_driver_t audio_null = { null_audio_write, null_audio_stop, null_audio_start, + null_audio_alive, null_audio_set_nonblock_state, null_audio_free, null_audio_use_float, diff --git a/audio/openal.c b/audio/openal.c index 2cf43d9fef..dd1ab31837 100644 --- a/audio/openal.c +++ b/audio/openal.c @@ -50,6 +50,7 @@ typedef struct al ALCcontext *ctx; bool nonblock; + bool is_paused; } al_t; static void al_free(void *data) @@ -204,10 +205,20 @@ static ssize_t al_write(void *data, const void *buf_, size_t size) static bool al_stop(void *data) { - (void)data; + al_t *al = (al_t*)data; + if (al) + al->is_paused = true; return true; } +static bool al_alive(void *data) +{ + al_t *al = (al_t*)data; + if (al) + return !al->is_paused; + return false; +} + static void al_set_nonblock_state(void *data, bool state) { al_t *al = (al_t*)data; @@ -216,7 +227,9 @@ static void al_set_nonblock_state(void *data, bool state) static bool al_start(void *data) { - (void)data; + al_t *al = (al_t*)data; + if (al) + al->is_paused = false; return true; } @@ -244,6 +257,7 @@ audio_driver_t audio_openal = { al_write, al_stop, al_start, + al_alive, al_set_nonblock_state, al_free, al_use_float, diff --git a/audio/opensl.c b/audio/opensl.c index bf520ef5e8..3ca86f28d7 100644 --- a/audio/opensl.c +++ b/audio/opensl.c @@ -52,6 +52,7 @@ typedef struct sl slock_t *lock; scond_t *cond; bool nonblock; + bool is_paused; unsigned buf_size; unsigned buf_count; } sl_t; @@ -199,7 +200,16 @@ error: static bool sl_stop(void *data) { sl_t *sl = (sl_t*)data; - return SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_STOPPED) == SL_RESULT_SUCCESS; + sl->is_paused = (SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_STOPPED) == SL_RESULT_SUCCESS) ? true : false; + return sl->is_paused ? true : false; +} + +static bool sl_alive(void *data) +{ + sl_t *sl = (sl_t*)data; + if (sl) + return !sl->is_paused; + return false; } static void sl_set_nonblock_state(void *data, bool state) @@ -211,7 +221,8 @@ static void sl_set_nonblock_state(void *data, bool state) static bool sl_start(void *data) { sl_t *sl = (sl_t*)data; - return SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING) == SL_RESULT_SUCCESS; + sl->is_paused = (SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING) == SL_RESULT_SUCCESS) ? false : true; + return sl->is_paused ? false : true; } @@ -289,6 +300,7 @@ audio_driver_t audio_opensl = { sl_write, sl_stop, sl_start, + sl_alive, sl_set_nonblock_state, sl_free, sl_use_float, diff --git a/audio/oss.c b/audio/oss.c index b633c24fc8..7d71a181d7 100644 --- a/audio/oss.c +++ b/audio/oss.c @@ -39,6 +39,8 @@ #define DEFAULT_OSS_DEV "/dev/dsp" #endif +static bool oss_is_paused; + static void *oss_init(const char *device, unsigned rate, unsigned latency) { int *fd = (int*)calloc(1, sizeof(int)); @@ -124,14 +126,23 @@ static bool oss_stop(void *data) { int *fd = (int*)data; ioctl(*fd, SNDCTL_DSP_RESET, 0); + oss_is_paused = true; return true; } static bool oss_start(void *data) { + (void)data; + oss_is_paused = false; return true; } +static bool oss_alive(void *data) +{ + (void)data; + return !oss_is_paused; +} + static void oss_set_nonblock_state(void *data, bool state) { int *fd = (int*)data; @@ -155,9 +166,9 @@ static void oss_free(void *data) static size_t oss_write_avail(void *data) { + audio_buf_info info; int *fd = (int*)data; - audio_buf_info info; if (ioctl(*fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { RARCH_ERR("SNDCTL_DSP_GETOSPACE failed ...\n"); @@ -169,9 +180,9 @@ static size_t oss_write_avail(void *data) static size_t oss_buffer_size(void *data) { + audio_buf_info info; int *fd = (int*)data; - audio_buf_info info; if (ioctl(*fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { RARCH_ERR("SNDCTL_DSP_GETOSPACE failed ...\n"); @@ -192,6 +203,7 @@ audio_driver_t audio_oss = { oss_write, oss_stop, oss_start, + oss_alive, oss_set_nonblock_state, oss_free, oss_use_float, diff --git a/audio/ps3_audio.c b/audio/ps3_audio.c index cfc39b2579..c80c7407a7 100644 --- a/audio/ps3_audio.c +++ b/audio/ps3_audio.c @@ -185,6 +185,12 @@ static bool ps3_audio_start(void *data) return true; } +static bool ps3_audio_alive(void *data) +{ + ps3_audio_t *aud = data; + return aud->started; +} + static void ps3_audio_set_nonblock_state(void *data, bool toggle) { ps3_audio_t *aud = data; @@ -223,6 +229,7 @@ audio_driver_t audio_ps3 = { ps3_audio_write, ps3_audio_stop, ps3_audio_start, + ps3_audio_alive, ps3_audio_set_nonblock_state, ps3_audio_free, ps3_audio_use_float, diff --git a/audio/psp1_audio.c b/audio/psp1_audio.c index 4f7915592d..ebb5d377f3 100644 --- a/audio/psp1_audio.c +++ b/audio/psp1_audio.c @@ -150,6 +150,14 @@ static ssize_t psp_audio_write(void *data, const void *buf, size_t size) return sampleCount; } +static bool psp_audio_alive(void *data) +{ + psp1_audio_t* psp = (psp1_audio_t*)data; + if (psp) + return psp->running; + return false; +} + static bool psp_audio_stop(void *data) { SceKernelThreadRunStatus runStatus; @@ -222,6 +230,7 @@ audio_driver_t audio_psp1 = { psp_audio_write, psp_audio_stop, psp_audio_start, + psp_audio_alive, psp_audio_set_nonblock_state, psp_audio_free, psp_audio_use_float, diff --git a/audio/pulse.c b/audio/pulse.c index 0b4ed54068..db6937df3d 100644 --- a/audio/pulse.c +++ b/audio/pulse.c @@ -30,6 +30,7 @@ typedef struct size_t buffer_size; bool nonblock; bool success; + bool is_paused; } pa_t; static void pulse_free(void *data) @@ -254,9 +255,18 @@ static bool pulse_stop(void *data) pa_threaded_mainloop_wait(pa->mainloop); bool ret = pa->success; pa_threaded_mainloop_unlock(pa->mainloop); + pa->is_paused = true; return ret; } +static bool pulse_alive(void *data) +{ + pa_t *pa = (pa_t*)data; + if (pa) + return !pa->is_paused; + return false; +} + static bool pulse_start(void *data) { RARCH_LOG("[PulseAudio]: Unpausing.\n"); @@ -267,6 +277,7 @@ static bool pulse_start(void *data) pa_threaded_mainloop_wait(pa->mainloop); bool ret = pa->success; pa_threaded_mainloop_unlock(pa->mainloop); + pa->is_paused = false; return ret; } @@ -303,6 +314,7 @@ audio_driver_t audio_pulse = { pulse_write, pulse_stop, pulse_start, + pulse_alive, pulse_set_nonblock_state, pulse_free, pulse_use_float, diff --git a/audio/roar.c b/audio/roar.c index 9c970cfcc8..8f25e5d0d4 100644 --- a/audio/roar.c +++ b/audio/roar.c @@ -78,10 +78,20 @@ static ssize_t ra_write(void *data, const void *buf, size_t size) static bool ra_stop(void *data) { - (void)data; + roar_t *roar = (roar_t*)data; + if (roar) + roar->is_paused = true; return true; } +static bool ra_alive(void *data) +{ + roar_t *roar = (roar_t*)data; + if (roar) + return !roar->is_paused; + return false; +} + static void ra_set_nonblock_state(void *data, bool state) { roar_t *roar = (roar_t*)data; @@ -92,7 +102,9 @@ static void ra_set_nonblock_state(void *data, bool state) static bool ra_start(void *data) { - (void)data; + roar_t *roar = (roar_t*)data; + if (roar) + roar->is_paused = false; return true; } @@ -114,6 +126,7 @@ audio_driver_t audio_roar = { ra_write, ra_stop, ra_start, + ra_alive, ra_set_nonblock_state, ra_free, ra_use_float, diff --git a/audio/rsound.c b/audio/rsound.c index c7819ab326..9a7989842e 100644 --- a/audio/rsound.c +++ b/audio/rsound.c @@ -25,6 +25,7 @@ typedef struct rsd { rsound_t *rd; bool nonblock; + bool is_paused; volatile bool has_error; fifo_buffer_t *buffer; @@ -146,6 +147,7 @@ static bool rs_stop(void *data) { rsd_t *rsd = (rsd_t*)data; rsd_stop(rsd->rd); + rsd->is_paused = true; return true; } @@ -156,11 +158,20 @@ static void rs_set_nonblock_state(void *data, bool state) rsd->nonblock = state; } +static bool rs_alive(void *data) +{ + rsd_t *rsd = (rsd_t*)data; + if (rsd) + return !rsd->is_paused; + return false; +} + static bool rs_start(void *data) { rsd_t *rsd = (rsd_t*)data; if (rsd_start(rsd->rd) < 0) return false; + rsd->is_paused = false; return true; } @@ -208,6 +219,7 @@ audio_driver_t audio_rsound = { rs_write, rs_stop, rs_start, + rs_alive, rs_set_nonblock_state, rs_free, rs_use_float, diff --git a/audio/rwebaudio.c b/audio/rwebaudio.c index 8e04c73429..deb7b39664 100644 --- a/audio/rwebaudio.c +++ b/audio/rwebaudio.c @@ -18,6 +18,8 @@ #include "../emscripten/RWebAudio.h" +static bool rwebaudio_is_paused; + static void rwebaudio_free(void *data) { RWebAudioFree(); @@ -42,6 +44,7 @@ static ssize_t rwebaudio_write(void *data, const void *buf, size_t size) static bool rwebaudio_stop(void *data) { (void)data; + rwebaudio_is_paused = true; return RWebAudioStop(); } @@ -51,9 +54,16 @@ static void rwebaudio_set_nonblock_state(void *data, bool state) RWebAudioSetNonblockState(state); } +static bool rwebaudio_alive(void *data) +{ + (void)data; + return !rwebaudio_is_paused; +} + static bool rwebaudio_start(void *data) { (void)data; + rwebaudio_is_paused = false; return RWebAudioStart(); } @@ -80,6 +90,7 @@ audio_driver_t audio_rwebaudio = { rwebaudio_write, rwebaudio_stop, rwebaudio_start, + rwebaudio_alive, rwebaudio_set_nonblock_state, rwebaudio_free, rwebaudio_use_float, diff --git a/audio/sdl_audio.c b/audio/sdl_audio.c index 7fcd125840..736f98bd14 100644 --- a/audio/sdl_audio.c +++ b/audio/sdl_audio.c @@ -31,6 +31,7 @@ typedef struct sdl_audio { bool nonblock; + bool is_paused; slock_t *lock; scond_t *cond; @@ -157,14 +158,25 @@ static ssize_t sdl_audio_write(void *data, const void *buf, size_t size) static bool sdl_audio_stop(void *data) { - (void)data; + sdl_audio_t *sdl = (sdl_audio_t*)data; + sdl->is_paused = true; SDL_PauseAudio(1); return true; } +static bool sdl_audio_alive(void *data) +{ + sdl_audio_t *sdl = (sdl_audio_t*)data; + if (sdl) + return !sdl->is_paused; + return false; +} + static bool sdl_audio_start(void *data) { - (void)data; + sdl_audio_t *sdl = (sdl_audio_t*)data; + sdl->is_paused = false; + SDL_PauseAudio(0); return true; } @@ -201,6 +213,7 @@ audio_driver_t audio_sdl = { sdl_audio_write, sdl_audio_stop, sdl_audio_start, + sdl_audio_alive, sdl_audio_set_nonblock_state, sdl_audio_free, sdl_use_float, diff --git a/audio/thread_wrapper.c b/audio/thread_wrapper.c index 7ab6a10027..c210daeabf 100644 --- a/audio/thread_wrapper.c +++ b/audio/thread_wrapper.c @@ -31,6 +31,7 @@ typedef struct audio_thread scond_t *cond; bool alive; bool stopped; + bool is_paused; bool use_float; int inited; @@ -132,10 +133,21 @@ static void audio_thread_free(void *data) free(thr); } +static bool audio_thread_alive(void *data) +{ + bool alive = false; + audio_thread_t *thr = (audio_thread_t*)data; + audio_thread_block(thr); + alive = !thr->is_paused; + audio_thread_unblock(thr); + return alive; +} + static bool audio_thread_stop(void *data) { audio_thread_t *thr = (audio_thread_t*)data; audio_thread_block(thr); + thr->is_paused = true; g_extern.system.audio_callback.set_state(false); return true; } @@ -144,6 +156,7 @@ static bool audio_thread_start(void *data) { audio_thread_t *thr = (audio_thread_t*)data; g_extern.system.audio_callback.set_state(true); + thr->is_paused = false; audio_thread_unblock(thr); return true; } @@ -181,6 +194,7 @@ static const audio_driver_t audio_thread = { audio_thread_write, audio_thread_stop, audio_thread_start, + audio_thread_alive, audio_thread_set_nonblock_state, audio_thread_free, audio_thread_use_float, diff --git a/audio/xaudio.c b/audio/xaudio.c index 8978e501f9..c0ff23a77b 100644 --- a/audio/xaudio.c +++ b/audio/xaudio.c @@ -23,6 +23,7 @@ typedef struct { xaudio2_t *xa; bool nonblock; + bool is_paused; size_t bufsize; } xa_t; @@ -80,10 +81,19 @@ static ssize_t xa_write(void *data, const void *buf, size_t size) static bool xa_stop(void *data) { - (void)data; + xa_t *xa = (xa_t*)data; + xa->is_paused = false; return true; } +static bool xa_alive(void *data) +{ + xa_t *xa = (xa_t*)data; + if (xa) + return !xa->is_paused; + return false; +} + static void xa_set_nonblock_state(void *data, bool state) { xa_t *xa = (xa_t*)data; @@ -92,7 +102,8 @@ static void xa_set_nonblock_state(void *data, bool state) static bool xa_start(void *data) { - (void)data; + xa_t *xa = (xa_t*)data; + xa->is_paused = false; return true; } @@ -130,6 +141,7 @@ audio_driver_t audio_xa = { xa_write, xa_stop, xa_start, + xa_alive, xa_set_nonblock_state, xa_free, xa_use_float, diff --git a/audio/xenon360_audio.c b/audio/xenon360_audio.c index e71df95891..64794e69e6 100644 --- a/audio/xenon360_audio.c +++ b/audio/xenon360_audio.c @@ -28,6 +28,7 @@ typedef struct { uint32_t buffer[2048]; bool nonblock; + bool is_paused; } xenon_audio_t; static void *xenon360_audio_init(const char *device, @@ -86,10 +87,19 @@ static ssize_t xenon360_audio_write(void *data, const void *buf, size_t size) static bool xenon360_audio_stop(void *data) { - (void)data; + xenon_audio_t *xa = data; + xa->is_paused = true; return true; } +static bool xenon360_audio_alive(void *data) +{ + xenon_audio_t *xa = data; + if (xa) + return !xa->is_paused; + return false; +} + static void xenon360_audio_set_nonblock_state(void *data, bool state) { xenon_audio_t *xa = data; @@ -98,7 +108,8 @@ static void xenon360_audio_set_nonblock_state(void *data, bool state) static bool xenon360_audio_start(void *data) { - (void)data; + xenon_audio_t *xa = data; + xa->is_paused = false; return true; } @@ -119,6 +130,7 @@ audio_driver_t audio_xenon360 = { xenon360_audio_write, xenon360_audio_stop, xenon360_audio_start, + xenon360_audio_alive, xenon360_audio_set_nonblock_state, xenon360_audio_free, xenon360_use_float, diff --git a/driver.h b/driver.h index cf88f70632..013d6fbe33 100644 --- a/driver.h +++ b/driver.h @@ -184,6 +184,9 @@ typedef struct audio_driver bool (*stop)(void *data); bool (*start)(void *data); + /* Is the audio driver currently running? */ + bool (*alive)(void *data); + /* Should we care about blocking in audio thread? Fast forwarding. */ void (*set_nonblock_state)(void *data, bool toggle); void (*free)(void *data); diff --git a/retroarch.c b/retroarch.c index 76861202a1..abe5b1338e 100644 --- a/retroarch.c +++ b/retroarch.c @@ -3137,11 +3137,22 @@ void rarch_main_command(unsigned cmd) #endif break; case RARCH_CMD_AUDIO_STOP: - if (driver.audio_data) - driver.audio->stop(driver.audio_data); + if (!driver.audio_data) + return; + + if (!driver.audio->alive(driver.audio_data)) + return; + + driver.audio->stop(driver.audio_data); break; case RARCH_CMD_AUDIO_START: - if (driver.audio_data && !g_extern.audio_data.mute + if (!driver.audio_data) + return; + + if (driver.audio->alive(driver.audio_data)) + return; + + if (!g_extern.audio_data.mute && !driver.audio->start(driver.audio_data)) { RARCH_ERR("Failed to start audio driver. Will continue without audio.\n");