Commit 92653f84 authored by Warren Dukes's avatar Warren Dukes

implemented dropping of current buffered audio, works for oss, but there seems

to be a "blip" for alsa devices, needs more work git-svn-id: https://svn.musicpd.org/mpd/trunk@3011 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent 7808fea9
...@@ -223,7 +223,10 @@ inline void syncAudioDevicesEnabledArrays() { ...@@ -223,7 +223,10 @@ inline void syncAudioDevicesEnabledArrays() {
if(myAudioDevicesEnabled[i]) { if(myAudioDevicesEnabled[i]) {
openAudioOutput(audioOutputArray[i], &audio_format); openAudioOutput(audioOutputArray[i], &audio_format);
} }
else closeAudioOutput(audioOutputArray[i]); else {
dropBufferedAudioOutput(audioOutputArray[i]);
closeAudioOutput(audioOutputArray[i]);
}
} }
} }
...@@ -312,6 +315,23 @@ int isAudioDeviceOpen() { ...@@ -312,6 +315,23 @@ int isAudioDeviceOpen() {
return audioOpened; 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() { void closeAudioDevice() {
int i; int i;
......
...@@ -57,6 +57,8 @@ int openAudioDevice(AudioFormat * audioFormat); ...@@ -57,6 +57,8 @@ int openAudioDevice(AudioFormat * audioFormat);
int playAudio(char * playChunk,int size); int playAudio(char * playChunk,int size);
void dropBufferedAudio();
void closeAudioDevice(); void closeAudioDevice();
int isAudioDeviceOpen(); int isAudioDeviceOpen();
......
...@@ -61,6 +61,7 @@ AudioOutput * newAudioOutput(ConfigParam * param) { ...@@ -61,6 +61,7 @@ AudioOutput * newAudioOutput(ConfigParam * param) {
ret->finishDriverFunc = plugin->finishDriverFunc; ret->finishDriverFunc = plugin->finishDriverFunc;
ret->openDeviceFunc = plugin->openDeviceFunc; ret->openDeviceFunc = plugin->openDeviceFunc;
ret->playFunc = plugin->playFunc; ret->playFunc = plugin->playFunc;
ret->dropBufferedAudioFunc = plugin->dropBufferedAudioFunc;
ret->closeDeviceFunc = plugin->closeDeviceFunc; ret->closeDeviceFunc = plugin->closeDeviceFunc;
ret->sendMetdataFunc = plugin->sendMetdataFunc; ret->sendMetdataFunc = plugin->sendMetdataFunc;
ret->open = 0; ret->open = 0;
...@@ -165,6 +166,10 @@ int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size) { ...@@ -165,6 +166,10 @@ int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size) {
return ret; return ret;
} }
void dropBufferedAudioOutput(AudioOutput * audioOutput) {
if(audioOutput->open) audioOutput->dropBufferedAudioFunc(audioOutput);
}
void closeAudioOutput(AudioOutput * audioOutput) { void closeAudioOutput(AudioOutput * audioOutput) {
if(audioOutput->open) audioOutput->closeDeviceFunc(audioOutput); if(audioOutput->open) audioOutput->closeDeviceFunc(audioOutput);
} }
......
...@@ -38,6 +38,8 @@ typedef int (* AudioOutputOpenDeviceFunc) (AudioOutput * audioOutput); ...@@ -38,6 +38,8 @@ typedef int (* AudioOutputOpenDeviceFunc) (AudioOutput * audioOutput);
typedef int (* AudioOutputPlayFunc) (AudioOutput * audioOutput, typedef int (* AudioOutputPlayFunc) (AudioOutput * audioOutput,
char * playChunk, int size); char * playChunk, int size);
typedef void (* AudioOutputDropBufferedAudioFunc) (AudioOutput * audioOutput);
typedef void (* AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput); typedef void (* AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput);
typedef void (* AudioOutputSendMetadataFunc) (AudioOutput * audioOutput, typedef void (* AudioOutputSendMetadataFunc) (AudioOutput * audioOutput,
...@@ -51,6 +53,7 @@ struct _AudioOutput { ...@@ -51,6 +53,7 @@ struct _AudioOutput {
AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputFinishDriverFunc finishDriverFunc;
AudioOutputOpenDeviceFunc openDeviceFunc; AudioOutputOpenDeviceFunc openDeviceFunc;
AudioOutputPlayFunc playFunc; AudioOutputPlayFunc playFunc;
AudioOutputDropBufferedAudioFunc dropBufferedAudioFunc;
AudioOutputCloseDeviceFunc closeDeviceFunc; AudioOutputCloseDeviceFunc closeDeviceFunc;
AudioOutputSendMetadataFunc sendMetdataFunc; AudioOutputSendMetadataFunc sendMetdataFunc;
...@@ -71,6 +74,7 @@ typedef struct _AudioOutputPlugin { ...@@ -71,6 +74,7 @@ typedef struct _AudioOutputPlugin {
AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputFinishDriverFunc finishDriverFunc;
AudioOutputOpenDeviceFunc openDeviceFunc; AudioOutputOpenDeviceFunc openDeviceFunc;
AudioOutputPlayFunc playFunc; AudioOutputPlayFunc playFunc;
AudioOutputDropBufferedAudioFunc dropBufferedAudioFunc;
AudioOutputCloseDeviceFunc closeDeviceFunc; AudioOutputCloseDeviceFunc closeDeviceFunc;
AudioOutputSendMetadataFunc sendMetdataFunc; AudioOutputSendMetadataFunc sendMetdataFunc;
} AudioOutputPlugin; } AudioOutputPlugin;
...@@ -84,6 +88,7 @@ void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); ...@@ -84,6 +88,7 @@ void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
AudioOutput * newAudioOutput(ConfigParam * param); AudioOutput * newAudioOutput(ConfigParam * param);
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat); int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat);
int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size); int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size);
void dropBufferedAudioOutput(AudioOutput * audioOutput);
void closeAudioOutput(AudioOutput * audioOutput); void closeAudioOutput(AudioOutput * audioOutput);
void finishAudioOutput(AudioOutput * audioOutput); void finishAudioOutput(AudioOutput * audioOutput);
int keepAudioOutputAlive(AudioOutput * audioOutput, int ms); int keepAudioOutputAlive(AudioOutput * audioOutput, int ms);
......
...@@ -117,14 +117,14 @@ static int alsa_openDevice(AudioOutput * audioOutput) ...@@ -117,14 +117,14 @@ static int alsa_openDevice(AudioOutput * audioOutput)
} }
err = snd_pcm_open(&ad->pcm_handle, ad->device, err = snd_pcm_open(&ad->pcm_handle, ad->device,
SND_PCM_STREAM_PLAYBACK, 0); SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if(err < 0) { if(err < 0) {
ad->pcm_handle = NULL; ad->pcm_handle = NULL;
goto error; goto error;
} }
/*err = snd_pcm_nonblock(ad->pcm_handle, 0); err = snd_pcm_nonblock(ad->pcm_handle, 0);
if(err < 0) goto error;*/ if(err < 0) goto error;
/* configure HW params */ /* configure HW params */
snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_alloca(&hwparams);
...@@ -221,28 +221,46 @@ fail: ...@@ -221,28 +221,46 @@ fail:
return -1; return -1;
} }
static void alsa_closeDevice(AudioOutput * audioOutput) { static void alsa_dropBufferedAudio(AudioOutput * audioOutput) {
AlsaData * ad = audioOutput->data; AlsaData * ad = audioOutput->data;
if(ad->pcm_handle) { snd_pcm_drop(ad->pcm_handle);
snd_pcm_drain(ad->pcm_handle);
ad->pcm_handle = NULL;
}
audioOutput->open = 0;
} }
inline static int alsa_errorRecovery(AlsaData * ad, int err) { inline static int alsa_errorRecovery(AlsaData * ad, int err) {
if(err == -EPIPE) { if(err == -EPIPE) {
DEBUG("Underrun on alsa device \"%s\"\n", ad->device); 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); err = snd_pcm_prepare(ad->pcm_handle);
if(err < 0) return -1; if(err < 0) return -1;
return 0; return 0;
default:
/* unknown state, do nothing */
break;
} }
return err; 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, static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk,
int size) int size)
{ {
...@@ -277,6 +295,7 @@ AudioOutputPlugin alsaPlugin = ...@@ -277,6 +295,7 @@ AudioOutputPlugin alsaPlugin =
alsa_finishDriver, alsa_finishDriver,
alsa_openDevice, alsa_openDevice,
alsa_playAudio, alsa_playAudio,
alsa_dropBufferedAudio,
alsa_closeDevice, alsa_closeDevice,
NULL /* sendMetadataFunc */ NULL /* sendMetadataFunc */
}; };
......
...@@ -171,6 +171,10 @@ static void audioOutputAo_finishDriver(AudioOutput * audioOutput) { ...@@ -171,6 +171,10 @@ static void audioOutputAo_finishDriver(AudioOutput * audioOutput) {
if(driverInitCount == 0) ao_shutdown(); if(driverInitCount == 0) ao_shutdown();
} }
static void audioOutputAo_dropBufferedAudio(AudioOutput * audioOutput) {
// not supported by libao
}
static void audioOutputAo_closeDevice(AudioOutput * audioOutput) { static void audioOutputAo_closeDevice(AudioOutput * audioOutput) {
AoData * ad = (AoData *) audioOutput->data; AoData * ad = (AoData *) audioOutput->data;
...@@ -237,6 +241,7 @@ AudioOutputPlugin aoPlugin = ...@@ -237,6 +241,7 @@ AudioOutputPlugin aoPlugin =
audioOutputAo_finishDriver, audioOutputAo_finishDriver,
audioOutputAo_openDevice, audioOutputAo_openDevice,
audioOutputAo_play, audioOutputAo_play,
audioOutputAo_dropBufferedAudio,
audioOutputAo_closeDevice, audioOutputAo_closeDevice,
NULL /* sendMetadataFunc */ NULL /* sendMetadataFunc */
}; };
...@@ -253,6 +258,7 @@ AudioOutputPlugin aoPlugin = ...@@ -253,6 +258,7 @@ AudioOutputPlugin aoPlugin =
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}; };
......
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
typedef struct _OssData { typedef struct _OssData {
int fd; int fd;
char * device; char * device;
int channels;
int sampleRate;
int bitFormat;
int bits;
} OssData; } OssData;
static OssData * newOssData() { static OssData * newOssData() {
...@@ -154,28 +158,45 @@ static void oss_finishDriver(AudioOutput * audioOutput) { ...@@ -154,28 +158,45 @@ static void oss_finishDriver(AudioOutput * audioOutput) {
freeOssData(od); freeOssData(od);
} }
static int oss_openDevice(AudioOutput * audioOutput) static int oss_open(AudioOutput * audioOutput) {
{
OssData * od = audioOutput->data; 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((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, &i)) 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, &od->channels)) {
if(ioctl(od->fd, SNDCTL_DSP_CHANNELS, &i)) goto fail; 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, &od->sampleRate)) {
if(ioctl(od->fd, SNDCTL_DSP_SPEED, &i)) goto fail; 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, &od->bits)) {
if(ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE, &i)) goto fail; ERROR("OSS device \"%s\" does not support %i bit audio: %s\n",
od->device,
od->bits,
strerror(errno));
goto fail;
}
audioOutput->open = 1; audioOutput->open = 1;
...@@ -184,11 +205,25 @@ static int oss_openDevice(AudioOutput * audioOutput) ...@@ -184,11 +205,25 @@ static int oss_openDevice(AudioOutput * audioOutput)
fail: fail:
if(od->fd >= 0) close(od->fd); if(od->fd >= 0) close(od->fd);
audioOutput->open = 0; audioOutput->open = 0;
ERROR("Error opening OSS device \"%s\": %s\n", od->device,
strerror(errno));
return -1; 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) { static void oss_closeDevice(AudioOutput * audioOutput) {
OssData * od = audioOutput->data; OssData * od = audioOutput->data;
...@@ -200,6 +235,17 @@ static void oss_closeDevice(AudioOutput * audioOutput) { ...@@ -200,6 +235,17 @@ static void oss_closeDevice(AudioOutput * audioOutput) {
audioOutput->open = 0; 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, static int oss_playAudio(AudioOutput * audioOutput, char * playChunk,
int size) int size)
{ {
...@@ -227,6 +273,7 @@ AudioOutputPlugin ossPlugin = ...@@ -227,6 +273,7 @@ AudioOutputPlugin ossPlugin =
oss_finishDriver, oss_finishDriver,
oss_openDevice, oss_openDevice,
oss_playAudio, oss_playAudio,
oss_dropBufferedAudio,
oss_closeDevice, oss_closeDevice,
NULL /* sendMetadataFunc */ NULL /* sendMetadataFunc */
}; };
...@@ -241,6 +288,7 @@ AudioOutputPlugin ossPlugin = ...@@ -241,6 +288,7 @@ AudioOutputPlugin ossPlugin =
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL /* sendMetadataFunc */ NULL /* sendMetadataFunc */
}; };
......
...@@ -361,6 +361,10 @@ static void myShout_finishDriver(AudioOutput * audioOutput) { ...@@ -361,6 +361,10 @@ static void myShout_finishDriver(AudioOutput * audioOutput) {
if(shoutInitCount == 0) shout_shutdown(); if(shoutInitCount == 0) shout_shutdown();
} }
static void myShout_dropBufferedAudioDevice(AudioOutput * audioOutput) {
// needs to be implemented
}
static void myShout_closeDevice(AudioOutput * audioOutput) { static void myShout_closeDevice(AudioOutput * audioOutput) {
ShoutData * sd = (ShoutData *)audioOutput->data; ShoutData * sd = (ShoutData *)audioOutput->data;
......
...@@ -251,6 +251,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb, ...@@ -251,6 +251,7 @@ int decodeSeek(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
} \ } \
} \ } \
if(pc->stop) { \ if(pc->stop) { \
dropBufferedAudio(); \
quitDecode(pc,dc); \ quitDecode(pc,dc); \
return; \ return; \
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment