From a25acbc94fb6e139c4484c3c93d3030a19494b2f Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 18 Mar 2006 03:58:31 +0000 Subject: rewrite statefile code for audio devices In the words of the original author, it was 'crappy'. I tend to agree :) The code has also been broken for at least the past few months, and nobody bothered fixing it The previous format it was overly complex: 5 lines to describe each device. The new format is one-line per-device: audio_device_state:%d:%s %d - 0 for disabled, any integer for enabled %s - name of the device as specified in the config file, whitespace and all Incompatibilities: * Output names are now _required_ to be unique. This is required because the new format relies solely on the name of the audio device. Relying on the device IDs internal to MPD was a bad idea anyways since the user usually has none or very little idea how they're generated, and adding a new device or removing one from a config would throw things off completely. This is also just a Good Idea(TM) because it makes things less confusing to users when they see it in their clients. * Output states are not preserved from the previous format. Not a big deal, since the previous code was never officially released. Also, it's been broken for months now, so I doubt anybody would notice :) git-svn-id: https://svn.musicpd.org/mpd/trunk@3928 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/audio.c | 193 ++++++++++++++++++++++++++++-------------------------------- 1 file changed, 91 insertions(+), 102 deletions(-) (limited to 'src/audio.c') diff --git a/src/audio.c b/src/audio.c index 8f7200d46..dfc209b32 100644 --- a/src/audio.c +++ b/src/audio.c @@ -34,18 +34,10 @@ #include #include - -/* crappy code by qball */ -#define AUDIO_STATE_FILE_DEVICE_START "audio_device_start" -#define AUDIO_STATE_FILE_DEVICE_ID "audio_device_id: " -#define AUDIO_STATE_FILE_DEVICE_ENABLED "audio_device_enabled: " -#define AUDIO_STATE_FILE_DEVICE_NAME "audio_device_name: " -#define AUDIO_STATE_FILE_DEVICE_END "audio_device_end" - +#define AUDIO_DEVICE_STATE "audio_device_state:" +#define AUDIO_DEVICE_STATE_LEN 19 /* strlen(AUDIO_DEVICE_STATE) */ #define AUDIO_BUFFER_SIZE 2*MAXPATHLEN -/* /crappy code */ - - +static void saveAudioDevicesState(); static AudioFormat audio_format; @@ -104,6 +96,9 @@ void initAudioDriver() { param = getNextConfigParam(CONF_AUDIO_OUTPUT, param); do { + AudioOutput *output; + int j; + if(audioOutputArraySize == AUDIO_MAX_DEVICES) { ERROR("only up to 255 audio output devices are " "supported"); @@ -114,14 +109,25 @@ void initAudioDriver() { audioOutputArray = realloc(audioOutputArray, audioOutputArraySize*sizeof(AudioOutput *)); - - audioOutputArray[i] = newAudioOutput(param); - if(!audioOutputArray[i] && param) { + output = newAudioOutput(param); + if(!output && param) { ERROR("problems configuring output device defined at " "line %i\n", param->line); exit(EXIT_FAILURE); } + + /* require output names to be unique: */ + for (j = i - 1; j >= 0; --j) { + if ( !strcmp( output->name, + audioOutputArray[j]->name) ) { + ERROR("output devices with identical " + "names: %s\n", + output->name); + exit(EXIT_FAILURE); + } + } + audioOutputArray[i] = output; } while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))); } @@ -221,6 +227,7 @@ void finishAudioConfig() { void finishAudioDriver() { int i; + saveAudioDevicesState(); for(i = 0; i < audioOutputArraySize; i++) { finishAudioOutput(audioOutputArray[i]); } @@ -415,115 +422,97 @@ void printAudioDevices(FILE * fp) { } } - -/* more qball crappy code */ - static char * getStateFile() { ConfigParam * param = parseConfigFilePath(CONF_STATE_FILE, 0); - + if(!param) return NULL; return param->value; } +static void saveAudioDevicesState() { + char *stateFile; + FILE *fp; + int i; + if (!(stateFile = getStateFile())) + return; -void saveAudioDevicesState() { - int i; - char * stateFile = getStateFile(); - - if(stateFile) { - FILE * fp; - - while(!(fp = fopen(stateFile,"a")) && errno==EINTR); - if(!fp) { - ERROR("problems opening state file \"%s\" for " - "writing: %s\n", stateFile, - strerror(errno)); - return; - } - for(i = 0; i < audioOutputArraySize; i++) { - myfprintf(fp, "%s\n", AUDIO_STATE_FILE_DEVICE_START); - myfprintf(fp, "%s%i\n", AUDIO_STATE_FILE_DEVICE_ID, i); - myfprintf(fp, "%s%s\n", AUDIO_STATE_FILE_DEVICE_NAME, audioOutputArray[i]->name); - myfprintf(fp, "%s%i\n", AUDIO_STATE_FILE_DEVICE_ENABLED,(int)pdAudioDevicesEnabled[i]); - myfprintf(fp, "%s\n", AUDIO_STATE_FILE_DEVICE_END); - } - while(fclose(fp) && errno==EINTR); + while(!(fp = fopen(stateFile,"a")) && errno==EINTR); + if(!fp) { + ERROR("problems opening state file \"%s\" for " + "writing: %s\n", stateFile, strerror(errno)); + return; + } + + assert(audioOutputArraySize != 0); + for (i = audioOutputArraySize - 1; i >= 0; --i) { + myfprintf(fp, AUDIO_DEVICE_STATE "%d:%s\n", + (int)pdAudioDevicesEnabled[i], + audioOutputArray[i]->name); } + while(fclose(fp) && errno==EINTR); } -void readAudioDevicesState() { - char * stateFile = getStateFile(); - FILE *fp; - struct stat st; - if(stateFile) { - char buffer[AUDIO_BUFFER_SIZE]; +static void parse_audio_device_state(FILE *fp) +{ + char buffer[AUDIO_BUFFER_SIZE]; + int i; + assert(audioOutputArraySize != 0); + while (myFgets(buffer,AUDIO_BUFFER_SIZE,fp)) { + char *c, *name; + if (strncmp(buffer,AUDIO_DEVICE_STATE,AUDIO_DEVICE_STATE_LEN)) + continue; - if(stat(stateFile,&st)<0) { - DEBUG("failed to stat state file\n"); - return; - } - if(!S_ISREG(st.st_mode)) { - ERROR("state file \"%s\" is not a regular " - "file\n",stateFile); - exit(EXIT_FAILURE); - } + c = strchr(buffer,':'); + if (!c || !(++c)) + goto errline; - fp = fopen(stateFile,"r"); - if(!fp) { - ERROR("problems opening state file \"%s\" for " - "reading: %s\n", stateFile, - strerror(errno)); - exit(EXIT_FAILURE); - } + name = strchr(c,':'); + if (!name || !(++name)) + goto errline; - while(myFgets(buffer,AUDIO_BUFFER_SIZE,fp)) { - if(strncmp(buffer,AUDIO_STATE_FILE_DEVICE_START, strlen(AUDIO_STATE_FILE_DEVICE_START))==0) { - char *name = NULL; - int id = -1; - int enabled = 1; - if(!myFgets(buffer,AUDIO_BUFFER_SIZE,fp)) { - ERROR("error parsing state file \"%s\"\n", stateFile); - exit(EXIT_FAILURE); - } - while(strcmp(buffer,AUDIO_STATE_FILE_DEVICE_END)) { - if(strncmp(buffer,AUDIO_STATE_FILE_DEVICE_ID, strlen(AUDIO_STATE_FILE_DEVICE_ID)) == 0 ) { - if(strlen(buffer) > strlen(AUDIO_STATE_FILE_DEVICE_ID)) - { - id = atoi(&buffer[strlen(AUDIO_STATE_FILE_DEVICE_ID)]); - } - } - if(strncmp(buffer,AUDIO_STATE_FILE_DEVICE_ENABLED, strlen(AUDIO_STATE_FILE_DEVICE_ENABLED)) == 0 ) { - if(strlen(buffer) > strlen(AUDIO_STATE_FILE_DEVICE_ENABLED)) - { - enabled = atoi(&buffer[strlen(AUDIO_STATE_FILE_DEVICE_ENABLED)]); - } - } - if(!myFgets(buffer,AUDIO_BUFFER_SIZE,fp)) { - ERROR("error parsing state file \"%s\"\n", stateFile); - exit(EXIT_FAILURE); - } - } - if(id != -1) - { - /* search for same name here, can we trust id? */ - if(id < audioOutputArraySize) - { - pdAudioDevicesEnabled[id] = enabled; - } - } - if(name != NULL) - { - free(name); - } + for (i = audioOutputArraySize - 1; i >= 0; --i) { + if (!strcmp(name, audioOutputArray[i]->name)) { + pdAudioDevicesEnabled[i] = atoi(c); + break; } } + continue; +errline: + /* nonfatal */ + ERROR("invalid line in state_file: %s\n", buffer); + } +} + +void readAudioDevicesState() { + char *stateFile; + FILE *fp; + struct stat st; - fclose(fp); + if (!(stateFile = getStateFile())) + return; + if(stat(stateFile,&st)<0) { + DEBUG("failed to stat state file\n"); + return; + } + if(!S_ISREG(st.st_mode)) { + ERROR("state file \"%s\" is not a regular file\n", + stateFile); + exit(EXIT_FAILURE); + } + + fp = fopen(stateFile,"r"); + if(!fp) { + ERROR("problems opening state file \"%s\" for " + "reading: %s\n", stateFile, + strerror(errno)); + exit(EXIT_FAILURE); } + parse_audio_device_state(fp); + fclose(fp); } -- cgit v1.2.3