diff options
Diffstat (limited to '')
-rw-r--r-- | src/audio.c | 22 | ||||
-rw-r--r-- | src/audio.h | 2 | ||||
-rw-r--r-- | src/audioOutput.c | 5 | ||||
-rw-r--r-- | src/audioOutput.h | 5 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_alsa.c | 39 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_ao.c | 6 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_oss.c | 86 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_shout.c | 4 | ||||
-rw-r--r-- | src/decode.c | 1 |
9 files changed, 140 insertions, 30 deletions
diff --git a/src/audio.c b/src/audio.c index cf2b54c20..728f93718 100644 --- a/src/audio.c +++ b/src/audio.c @@ -223,7 +223,10 @@ inline void syncAudioDevicesEnabledArrays() { if(myAudioDevicesEnabled[i]) { openAudioOutput(audioOutputArray[i], &audio_format); } - else closeAudioOutput(audioOutputArray[i]); + else { + dropBufferedAudioOutput(audioOutputArray[i]); + closeAudioOutput(audioOutputArray[i]); + } } } @@ -312,6 +315,23 @@ int isAudioDeviceOpen() { return audioOpened; } +void dropBufferedAudio() { + int i; + + if(0 != memcmp(pdAudioDevicesEnabled, myAudioDevicesEnabled, + AUDIO_MAX_DEVICES)) + { + syncAudioDevicesEnabledArrays(); + } + + audioBufferPos = 0; + + for(i = 0; i < audioOutputArraySize; i++) { + if(!myAudioDevicesEnabled[i]) continue; + dropBufferedAudioOutput(audioOutputArray[i]); + } +} + void closeAudioDevice() { int i; diff --git a/src/audio.h b/src/audio.h index 9dac621a1..87c265568 100644 --- a/src/audio.h +++ b/src/audio.h @@ -57,6 +57,8 @@ int openAudioDevice(AudioFormat * audioFormat); int playAudio(char * playChunk,int size); +void dropBufferedAudio(); + void closeAudioDevice(); int isAudioDeviceOpen(); diff --git a/src/audioOutput.c b/src/audioOutput.c index 1968c4b39..c973e1beb 100644 --- a/src/audioOutput.c +++ b/src/audioOutput.c @@ -61,6 +61,7 @@ AudioOutput * newAudioOutput(ConfigParam * param) { ret->finishDriverFunc = plugin->finishDriverFunc; ret->openDeviceFunc = plugin->openDeviceFunc; ret->playFunc = plugin->playFunc; + ret->dropBufferedAudioFunc = plugin->dropBufferedAudioFunc; ret->closeDeviceFunc = plugin->closeDeviceFunc; ret->sendMetdataFunc = plugin->sendMetdataFunc; ret->open = 0; @@ -165,6 +166,10 @@ int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size) { return ret; } +void dropBufferedAudioOutput(AudioOutput * audioOutput) { + if(audioOutput->open) audioOutput->dropBufferedAudioFunc(audioOutput); +} + void closeAudioOutput(AudioOutput * audioOutput) { if(audioOutput->open) audioOutput->closeDeviceFunc(audioOutput); } diff --git a/src/audioOutput.h b/src/audioOutput.h index 787891fbf..13c549555 100644 --- a/src/audioOutput.h +++ b/src/audioOutput.h @@ -38,6 +38,8 @@ typedef int (* AudioOutputOpenDeviceFunc) (AudioOutput * audioOutput); typedef int (* AudioOutputPlayFunc) (AudioOutput * audioOutput, char * playChunk, int size); +typedef void (* AudioOutputDropBufferedAudioFunc) (AudioOutput * audioOutput); + typedef void (* AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput); typedef void (* AudioOutputSendMetadataFunc) (AudioOutput * audioOutput, @@ -51,6 +53,7 @@ struct _AudioOutput { AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputOpenDeviceFunc openDeviceFunc; AudioOutputPlayFunc playFunc; + AudioOutputDropBufferedAudioFunc dropBufferedAudioFunc; AudioOutputCloseDeviceFunc closeDeviceFunc; AudioOutputSendMetadataFunc sendMetdataFunc; @@ -71,6 +74,7 @@ typedef struct _AudioOutputPlugin { AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputOpenDeviceFunc openDeviceFunc; AudioOutputPlayFunc playFunc; + AudioOutputDropBufferedAudioFunc dropBufferedAudioFunc; AudioOutputCloseDeviceFunc closeDeviceFunc; AudioOutputSendMetadataFunc sendMetdataFunc; } AudioOutputPlugin; @@ -84,6 +88,7 @@ void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); AudioOutput * newAudioOutput(ConfigParam * param); int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat); int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size); +void dropBufferedAudioOutput(AudioOutput * audioOutput); void closeAudioOutput(AudioOutput * audioOutput); void finishAudioOutput(AudioOutput * audioOutput); int keepAudioOutputAlive(AudioOutput * audioOutput, int ms); diff --git a/src/audioOutputs/audioOutput_alsa.c b/src/audioOutputs/audioOutput_alsa.c index 97dad496b..9730ade36 100644 --- a/src/audioOutputs/audioOutput_alsa.c +++ b/src/audioOutputs/audioOutput_alsa.c @@ -117,14 +117,14 @@ static int alsa_openDevice(AudioOutput * audioOutput) } err = snd_pcm_open(&ad->pcm_handle, ad->device, - SND_PCM_STREAM_PLAYBACK, 0); + SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if(err < 0) { ad->pcm_handle = NULL; goto error; } - /*err = snd_pcm_nonblock(ad->pcm_handle, 0); - if(err < 0) goto error;*/ + err = snd_pcm_nonblock(ad->pcm_handle, 0); + if(err < 0) goto error; /* configure HW params */ snd_pcm_hw_params_alloca(&hwparams); @@ -221,28 +221,46 @@ fail: return -1; } -static void alsa_closeDevice(AudioOutput * audioOutput) { +static void alsa_dropBufferedAudio(AudioOutput * audioOutput) { AlsaData * ad = audioOutput->data; - if(ad->pcm_handle) { - snd_pcm_drain(ad->pcm_handle); - ad->pcm_handle = NULL; - } - - audioOutput->open = 0; + snd_pcm_drop(ad->pcm_handle); } inline static int alsa_errorRecovery(AlsaData * ad, int err) { if(err == -EPIPE) { DEBUG("Underrun on alsa device \"%s\"\n", ad->device); + } + else if(err == -ESTRPIPE) { + DEBUG("alsa device \"%s\" was suspended\n", ad->device); + } + + switch(snd_pcm_state(ad->pcm_handle)) { + case SND_PCM_STATE_SETUP: + case SND_PCM_STATE_XRUN: err = snd_pcm_prepare(ad->pcm_handle); if(err < 0) return -1; return 0; + default: + /* unknown state, do nothing */ + break; } return err; } +static void alsa_closeDevice(AudioOutput * audioOutput) { + AlsaData * ad = audioOutput->data; + + if(ad->pcm_handle) { + snd_pcm_drain(ad->pcm_handle); + snd_pcm_close(ad->pcm_handle); + ad->pcm_handle = NULL; + } + + audioOutput->open = 0; +} + static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk, int size) { @@ -277,6 +295,7 @@ AudioOutputPlugin alsaPlugin = alsa_finishDriver, alsa_openDevice, alsa_playAudio, + alsa_dropBufferedAudio, alsa_closeDevice, NULL /* sendMetadataFunc */ }; diff --git a/src/audioOutputs/audioOutput_ao.c b/src/audioOutputs/audioOutput_ao.c index ee3457197..380e6e9d5 100644 --- a/src/audioOutputs/audioOutput_ao.c +++ b/src/audioOutputs/audioOutput_ao.c @@ -171,6 +171,10 @@ static void audioOutputAo_finishDriver(AudioOutput * audioOutput) { if(driverInitCount == 0) ao_shutdown(); } +static void audioOutputAo_dropBufferedAudio(AudioOutput * audioOutput) { + // not supported by libao +} + static void audioOutputAo_closeDevice(AudioOutput * audioOutput) { AoData * ad = (AoData *) audioOutput->data; @@ -237,6 +241,7 @@ AudioOutputPlugin aoPlugin = audioOutputAo_finishDriver, audioOutputAo_openDevice, audioOutputAo_play, + audioOutputAo_dropBufferedAudio, audioOutputAo_closeDevice, NULL /* sendMetadataFunc */ }; @@ -253,6 +258,7 @@ AudioOutputPlugin aoPlugin = NULL, NULL, NULL, + NULL, NULL }; diff --git a/src/audioOutputs/audioOutput_oss.c b/src/audioOutputs/audioOutput_oss.c index 76de8de82..fce622c5d 100644 --- a/src/audioOutputs/audioOutput_oss.c +++ b/src/audioOutputs/audioOutput_oss.c @@ -48,6 +48,10 @@ typedef struct _OssData { int fd; char * device; + int channels; + int sampleRate; + int bitFormat; + int bits; } OssData; static OssData * newOssData() { @@ -154,28 +158,45 @@ static void oss_finishDriver(AudioOutput * audioOutput) { freeOssData(od); } -static int oss_openDevice(AudioOutput * audioOutput) -{ +static int oss_open(AudioOutput * audioOutput) { OssData * od = audioOutput->data; - AudioFormat * audioFormat = &audioOutput->outAudioFormat; -#ifdef WORDS_BIGENDIAN - int i = AFMT_S16_BE; -#else - int i = AFMT_S16_LE; -#endif - - if((od->fd = open(od->device, O_WRONLY)) < 0) goto fail; - if(ioctl(od->fd, SNDCTL_DSP_SETFMT, &i)) goto fail; + if((od->fd = open(od->device, O_WRONLY)) < 0) { + ERROR("Error opening OSS device \"%s\": %s\n", od->device, + strerror(errno)); + goto fail; + } + + if(ioctl(od->fd, SNDCTL_DSP_SETFMT, &od->bitFormat)) { + ERROR("Error setting bitformat on OSS device \"%s\": %s\n", + od->device, + strerror(errno)); + goto fail; + } - i = audioFormat->channels; - if(ioctl(od->fd, SNDCTL_DSP_CHANNELS, &i)) goto fail; + if(ioctl(od->fd, SNDCTL_DSP_CHANNELS, &od->channels)) { + ERROR("OSS device \"%s\" does not support %i channels: %s\n", + od->device, + od->channels, + strerror(errno)); + goto fail; + } - i = audioFormat->sampleRate; - if(ioctl(od->fd, SNDCTL_DSP_SPEED, &i)) goto fail; + if(ioctl(od->fd, SNDCTL_DSP_SPEED, &od->sampleRate)) { + ERROR("OSS device \"%s\" does not support %i Hz audio: %s\n", + od->device, + od->sampleRate, + strerror(errno)); + goto fail; + } - i = audioFormat->bits; - if(ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE, &i)) goto fail; + if(ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE, &od->bits)) { + ERROR("OSS device \"%s\" does not support %i bit audio: %s\n", + od->device, + od->bits, + strerror(errno)); + goto fail; + } audioOutput->open = 1; @@ -184,11 +205,25 @@ static int oss_openDevice(AudioOutput * audioOutput) fail: if(od->fd >= 0) close(od->fd); audioOutput->open = 0; - ERROR("Error opening OSS device \"%s\": %s\n", od->device, - strerror(errno)); return -1; } +static int oss_openDevice(AudioOutput * audioOutput) +{ + OssData * od = audioOutput->data; + AudioFormat * audioFormat = &audioOutput->outAudioFormat; +#ifdef WORDS_BIGENDIAN + od->bitFormat = AFMT_S16_BE; +#else + od->bitFormat = AFMT_S16_LE; +#endif + od->channels = audioFormat->channels; + od->sampleRate = audioFormat->sampleRate; + od->bits = audioFormat->bits; + + return oss_open(audioOutput); +} + static void oss_closeDevice(AudioOutput * audioOutput) { OssData * od = audioOutput->data; @@ -200,6 +235,17 @@ static void oss_closeDevice(AudioOutput * audioOutput) { audioOutput->open = 0; } +static void oss_dropBufferedAudio(AudioOutput * audioOutput) { + OssData * od = audioOutput->data; + + if(od->fd >= 0) { + ioctl(od->fd, SNDCTL_DSP_RESET, 0); + oss_closeDevice(audioOutput); + } + + /*oss_open(audioOutput);*/ +} + static int oss_playAudio(AudioOutput * audioOutput, char * playChunk, int size) { @@ -227,6 +273,7 @@ AudioOutputPlugin ossPlugin = oss_finishDriver, oss_openDevice, oss_playAudio, + oss_dropBufferedAudio, oss_closeDevice, NULL /* sendMetadataFunc */ }; @@ -241,6 +288,7 @@ AudioOutputPlugin ossPlugin = NULL, NULL, NULL, + NULL, NULL /* sendMetadataFunc */ }; diff --git a/src/audioOutputs/audioOutput_shout.c b/src/audioOutputs/audioOutput_shout.c index 685b1cca2..1276e6b78 100644 --- a/src/audioOutputs/audioOutput_shout.c +++ b/src/audioOutputs/audioOutput_shout.c @@ -361,6 +361,10 @@ static void myShout_finishDriver(AudioOutput * audioOutput) { if(shoutInitCount == 0) shout_shutdown(); } +static void myShout_dropBufferedAudioDevice(AudioOutput * audioOutput) { + // needs to be implemented +} + static void myShout_closeDevice(AudioOutput * audioOutput) { ShoutData * sd = (ShoutData *)audioOutput->data; diff --git a/src/decode.c b/src/decode.c index 893e1a55c..4416552e1 100644 --- a/src/decode.c +++ b/src/decode.c @@ -251,6 +251,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, } \ } \ if(pc->stop) { \ + dropBufferedAudio(); \ quitDecode(pc,dc); \ return; \ } |