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
This commit is contained in:
Eric Wong 2006-07-16 16:53:04 +00:00
parent ea6dc826a1
commit b8a0f1ae6d
2 changed files with 37 additions and 18 deletions

View File

@ -421,6 +421,12 @@ static int setParam(OssData * od, int param, int * value) {
return 0; 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) { static int oss_open(AudioOutput * audioOutput) {
int tmp; int tmp;
OssData * od = audioOutput->data; OssData * od = audioOutput->data;
@ -468,7 +474,7 @@ static int oss_open(AudioOutput * audioOutput) {
return 0; return 0;
fail: fail:
if(od->fd >= 0) close(od->fd); oss_close(od);
audioOutput->open = 0; audioOutput->open = 0;
return -1; return -1;
} }
@ -483,7 +489,8 @@ static int oss_openDevice(AudioOutput * audioOutput)
od->sampleRate = audioFormat->sampleRate; od->sampleRate = audioFormat->sampleRate;
od->bits = audioFormat->bits; od->bits = audioFormat->bits;
ret = oss_open(audioOutput); if ((ret = oss_open(audioOutput)) < 0)
return ret;
audioFormat->channels = od->channels; audioFormat->channels = od->channels;
audioFormat->sampleRate = od->sampleRate; audioFormat->sampleRate = od->sampleRate;
@ -496,11 +503,6 @@ static int oss_openDevice(AudioOutput * audioOutput)
return ret; return ret;
} }
static void oss_close(OssData * od) {
if(od->fd >= 0) close(od->fd);
od->fd = -1;
}
static void oss_closeDevice(AudioOutput * audioOutput) { static void oss_closeDevice(AudioOutput * audioOutput) {
OssData * od = audioOutput->data; OssData * od = audioOutput->data;
@ -516,8 +518,6 @@ static void oss_dropBufferedAudio(AudioOutput * audioOutput) {
ioctl(od->fd, SNDCTL_DSP_RESET, 0); ioctl(od->fd, SNDCTL_DSP_RESET, 0);
oss_close(od); oss_close(od);
} }
/*oss_open(audioOutput);*/
} }
static int oss_playAudio(AudioOutput * audioOutput, char * playChunk, static int oss_playAudio(AudioOutput * audioOutput, char * playChunk,
@ -527,7 +527,8 @@ static int oss_playAudio(AudioOutput * audioOutput, char * playChunk,
int ret; int ret;
/* reopen the device since it was closed by dropBufferedAudio */ /* 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) { while (size > 0) {
ret = write(od->fd, playChunk, size); ret = write(od->fd, playChunk, size);

View File

@ -64,7 +64,7 @@ static char * volume_mixerDevice = VOLUME_MIXER_DEVICE_DEFAULT;
static int volume_softwareSet = 100; static int volume_softwareSet = 100;
#ifdef HAVE_OSS #ifdef HAVE_OSS
static int volume_ossFd; static int volume_ossFd = -1;
static int volume_ossControl = SOUND_MIXER_PCM; static int volume_ossControl = SOUND_MIXER_PCM;
#endif #endif
@ -77,8 +77,14 @@ static int volume_alsaSet = -1;
#endif #endif
#ifdef HAVE_OSS #ifdef HAVE_OSS
static void closeOssMixer(void)
{
while (close(volume_ossFd) && errno == EINTR);
volume_ossFd = -1;
}
static int prepOssMixer(char * device) { static int prepOssMixer(char * device) {
int devmask = 0;
ConfigParam * param; ConfigParam * param;
if((volume_ossFd = open(device,O_RDONLY))<0) { 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 * labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
char * dup; char * dup;
int i,j; int i,j;
int devmask = 0;
if(ioctl(volume_ossFd,SOUND_MIXER_READ_DEVMASK,&devmask)<0) { if(ioctl(volume_ossFd,SOUND_MIXER_READ_DEVMASK,&devmask)<0) {
WARNING("errors getting read_devmask for oss mixer\n"); WARNING("errors getting read_devmask for oss mixer\n");
close(volume_ossFd); closeOssMixer();
return -1; return -1;
} }
@ -114,13 +121,13 @@ static int prepOssMixer(char * device) {
if(i>=SOUND_MIXER_NRDEVICES) { if(i>=SOUND_MIXER_NRDEVICES) {
WARNING("mixer control \"%s\" not found at line %i\n", WARNING("mixer control \"%s\" not found at line %i\n",
param->value, param->line); param->value, param->line);
close(volume_ossFd); closeOssMixer();
return -1; return -1;
} }
else if(!( ( 1 << i ) & devmask )) { else if(!( ( 1 << i ) & devmask )) {
WARNING("mixer control \"%s\" not usable at line %i\n", WARNING("mixer control \"%s\" not usable at line %i\n",
param->value, param->line); param->value, param->line);
close(volume_ossFd); closeOssMixer();
return -1; return -1;
} }
@ -130,14 +137,21 @@ static int prepOssMixer(char * device) {
return 0; return 0;
} }
static void closeOssMixer() { static int ensure_oss_open(void)
close(volume_ossFd); {
if ((volume_ossFd < 0 && prepOssMixer(volume_mixerDevice) < 0))
return -1;
return 0;
} }
static int getOssVolumeLevel() { static int getOssVolumeLevel() {
int left, right, level; int left, right, level;
if (ensure_oss_open() < 0)
return -1;
if(ioctl(volume_ossFd,MIXER_READ(volume_ossControl),&level) < 0) { if(ioctl(volume_ossFd,MIXER_READ(volume_ossControl),&level) < 0) {
closeOssMixer();
WARNING("unable to read volume\n"); WARNING("unable to read volume\n");
return -1; return -1;
} }
@ -166,8 +180,11 @@ static int changeOssVolumeLevel(FILE * fp, int change, int rel) {
} }
new = current+change; new = current+change;
} else {
if (ensure_oss_open() < 0)
return -1;
new = change;
} }
else new = change;
if(new<0) new = 0; if(new<0) new = 0;
else if(new>100) new = 100; else if(new>100) new = 100;
@ -175,6 +192,7 @@ static int changeOssVolumeLevel(FILE * fp, int change, int rel) {
level = (new << 8) + new; level = (new << 8) + new;
if(ioctl(volume_ossFd,MIXER_WRITE(volume_ossControl),&level) < 0) { if(ioctl(volume_ossFd,MIXER_WRITE(volume_ossControl),&level) < 0) {
closeOssMixer();
commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume", commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume",
NULL); NULL);
return -1; return -1;