From b8a0f1ae6d32847270748e92e744606107114737 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 16 Jul 2006 16:53:04 +0000 Subject: OSS: handle device disconnects and reconnects (w/o needing a mpd restart) Like the ALSA patches, this allows OSS devices to be disconnected during playback and MPD will be able to reopen and reuse them without restarting. git-svn-id: https://svn.musicpd.org/mpd/trunk@4366 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/audioOutputs/audioOutput_oss.c | 21 +++++++++++---------- src/volume.c | 34 ++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/audioOutputs/audioOutput_oss.c b/src/audioOutputs/audioOutput_oss.c index 02403124e..3b52b9807 100644 --- a/src/audioOutputs/audioOutput_oss.c +++ b/src/audioOutputs/audioOutput_oss.c @@ -421,6 +421,12 @@ static int setParam(OssData * od, int param, int * value) { return 0; } +static void oss_close(OssData * od) +{ + if(od->fd >= 0) while (close(od->fd) && errno == EINTR); + od->fd = -1; +} + static int oss_open(AudioOutput * audioOutput) { int tmp; OssData * od = audioOutput->data; @@ -468,7 +474,7 @@ static int oss_open(AudioOutput * audioOutput) { return 0; fail: - if(od->fd >= 0) close(od->fd); + oss_close(od); audioOutput->open = 0; return -1; } @@ -483,7 +489,8 @@ static int oss_openDevice(AudioOutput * audioOutput) od->sampleRate = audioFormat->sampleRate; od->bits = audioFormat->bits; - ret = oss_open(audioOutput); + if ((ret = oss_open(audioOutput)) < 0) + return ret; audioFormat->channels = od->channels; audioFormat->sampleRate = od->sampleRate; @@ -496,11 +503,6 @@ static int oss_openDevice(AudioOutput * audioOutput) return ret; } -static void oss_close(OssData * od) { - if(od->fd >= 0) close(od->fd); - od->fd = -1; -} - static void oss_closeDevice(AudioOutput * audioOutput) { OssData * od = audioOutput->data; @@ -516,8 +518,6 @@ static void oss_dropBufferedAudio(AudioOutput * audioOutput) { ioctl(od->fd, SNDCTL_DSP_RESET, 0); oss_close(od); } - - /*oss_open(audioOutput);*/ } static int oss_playAudio(AudioOutput * audioOutput, char * playChunk, @@ -527,7 +527,8 @@ static int oss_playAudio(AudioOutput * audioOutput, char * playChunk, int ret; /* reopen the device since it was closed by dropBufferedAudio */ - if(od->fd < 0) oss_open(audioOutput); + if(od->fd < 0 && oss_open(audioOutput) < 0) + return -1; while (size > 0) { ret = write(od->fd, playChunk, size); diff --git a/src/volume.c b/src/volume.c index 6fd68d778..d398457d3 100644 --- a/src/volume.c +++ b/src/volume.c @@ -64,7 +64,7 @@ static char * volume_mixerDevice = VOLUME_MIXER_DEVICE_DEFAULT; static int volume_softwareSet = 100; #ifdef HAVE_OSS -static int volume_ossFd; +static int volume_ossFd = -1; static int volume_ossControl = SOUND_MIXER_PCM; #endif @@ -77,8 +77,14 @@ static int volume_alsaSet = -1; #endif #ifdef HAVE_OSS + +static void closeOssMixer(void) +{ + while (close(volume_ossFd) && errno == EINTR); + volume_ossFd = -1; +} + static int prepOssMixer(char * device) { - int devmask = 0; ConfigParam * param; if((volume_ossFd = open(device,O_RDONLY))<0) { @@ -92,10 +98,11 @@ static int prepOssMixer(char * device) { char * labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS; char * dup; int i,j; + int devmask = 0; if(ioctl(volume_ossFd,SOUND_MIXER_READ_DEVMASK,&devmask)<0) { WARNING("errors getting read_devmask for oss mixer\n"); - close(volume_ossFd); + closeOssMixer(); return -1; } @@ -114,13 +121,13 @@ static int prepOssMixer(char * device) { if(i>=SOUND_MIXER_NRDEVICES) { WARNING("mixer control \"%s\" not found at line %i\n", param->value, param->line); - close(volume_ossFd); + closeOssMixer(); return -1; } else if(!( ( 1 << i ) & devmask )) { WARNING("mixer control \"%s\" not usable at line %i\n", param->value, param->line); - close(volume_ossFd); + closeOssMixer(); return -1; } @@ -130,14 +137,21 @@ static int prepOssMixer(char * device) { return 0; } -static void closeOssMixer() { - close(volume_ossFd); +static int ensure_oss_open(void) +{ + if ((volume_ossFd < 0 && prepOssMixer(volume_mixerDevice) < 0)) + return -1; + return 0; } static int getOssVolumeLevel() { int left, right, level; + if (ensure_oss_open() < 0) + return -1; + if(ioctl(volume_ossFd,MIXER_READ(volume_ossControl),&level) < 0) { + closeOssMixer(); WARNING("unable to read volume\n"); return -1; } @@ -166,8 +180,11 @@ static int changeOssVolumeLevel(FILE * fp, int change, int rel) { } new = current+change; + } else { + if (ensure_oss_open() < 0) + return -1; + new = change; } - else new = change; if(new<0) new = 0; else if(new>100) new = 100; @@ -175,6 +192,7 @@ static int changeOssVolumeLevel(FILE * fp, int change, int rel) { level = (new << 8) + new; if(ioctl(volume_ossFd,MIXER_WRITE(volume_ossControl),&level) < 0) { + closeOssMixer(); commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume", NULL); return -1; -- cgit v1.2.3