aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/audio.c22
-rw-r--r--src/audio.h2
-rw-r--r--src/audioOutput.c5
-rw-r--r--src/audioOutput.h5
-rw-r--r--src/audioOutputs/audioOutput_alsa.c39
-rw-r--r--src/audioOutputs/audioOutput_ao.c6
-rw-r--r--src/audioOutputs/audioOutput_oss.c86
-rw-r--r--src/audioOutputs/audioOutput_shout.c4
-rw-r--r--src/decode.c1
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; \
}