diff options
Diffstat (limited to '')
-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 |
4 files changed, 106 insertions, 29 deletions
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; |