diff options
Diffstat (limited to '')
-rw-r--r-- | src/audio.c | 107 | ||||
-rw-r--r-- | src/audioOutput.c | 40 | ||||
-rw-r--r-- | src/audioOutput.h | 8 | ||||
-rw-r--r-- | src/audioOutput_ao.c | 41 | ||||
-rw-r--r-- | src/audioOutput_shout.c | 84 | ||||
-rw-r--r-- | src/conf.c | 566 | ||||
-rw-r--r-- | src/conf.h | 111 | ||||
-rw-r--r-- | src/directory.c | 3 | ||||
-rw-r--r-- | src/inputStream_http.c | 108 | ||||
-rw-r--r-- | src/interface.c | 81 | ||||
-rw-r--r-- | src/list.c | 2 | ||||
-rw-r--r-- | src/list.h | 1 | ||||
-rw-r--r-- | src/listen.c | 20 | ||||
-rw-r--r-- | src/log.c | 16 | ||||
-rw-r--r-- | src/main.c | 35 | ||||
-rw-r--r-- | src/path.c | 9 | ||||
-rw-r--r-- | src/permission.c | 57 | ||||
-rw-r--r-- | src/playerData.c | 40 | ||||
-rw-r--r-- | src/playlist.c | 54 | ||||
-rw-r--r-- | src/replayGain.c | 26 | ||||
-rw-r--r-- | src/tag.c | 12 | ||||
-rw-r--r-- | src/volume.c | 85 |
22 files changed, 915 insertions, 591 deletions
diff --git a/src/audio.c b/src/audio.c index 653fb55f5..e3a311abb 100644 --- a/src/audio.c +++ b/src/audio.c @@ -31,9 +31,6 @@ static AudioFormat audio_format; static AudioFormat * audio_configFormat = NULL; -static AudioOutput * aoOutput = NULL; -static AudioOutput * shoutOutput = NULL; - void copyAudioFormat(AudioFormat * dest, AudioFormat * src) { if(!src) return; @@ -42,17 +39,34 @@ void copyAudioFormat(AudioFormat * dest, AudioFormat * src) { dest->channels = src->channels; } +static AudioOutput ** audioOutputArray = NULL; +static int audioOutputArraySize = 0; + extern AudioOutputPlugin aoPlugin; extern AudioOutputPlugin shoutPlugin; void initAudioDriver() { + ConfigParam * param = NULL; + int i; + initAudioOutputPlugins(); loadAudioOutputPlugin(&aoPlugin); loadAudioOutputPlugin(&shoutPlugin); - aoOutput = newAudioOutput("ao"); - assert(aoOutput); - shoutOutput = newAudioOutput("shout"); + while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))) { + i = audioOutputArraySize++; + + audioOutputArray = realloc(audioOutputArray, + audioOutputArraySize*sizeof(AudioOutput *)); + + audioOutputArray[i] = newAudioOutput(param); + + if(!audioOutputArray[i]) { + ERROR("problems configuring output device defined at " + "line %i\n", param->line); + exit(EXIT_FAILURE); + } + } } void getOutputAudioFormat(AudioFormat * inAudioFormat, @@ -65,13 +79,17 @@ void getOutputAudioFormat(AudioFormat * inAudioFormat, } void initAudioConfig() { - char * conf = getConf()[CONF_AUDIO_OUTPUT_FORMAT]; + ConfigParam * param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT); - if(NULL == conf) return; + if(NULL == param || NULL == param->value) return; audio_configFormat = malloc(sizeof(AudioFormat)); - if(0 != parseAudioConfig(audio_configFormat, conf)) exit(EXIT_FAILURE); + if(0 != parseAudioConfig(audio_configFormat, param->value)) { + ERROR("error parsing \"%s\" at line %i\n", + CONF_AUDIO_OUTPUT_FORMAT, param->line); + exit(EXIT_FAILURE); + } } int parseAudioConfig(AudioFormat * audioFormat, char * conf) { @@ -145,10 +163,15 @@ void finishAudioConfig() { } void finishAudioDriver() { - finishAudioOutput(aoOutput); - if(shoutOutput) finishAudioOutput(shoutOutput); - shoutOutput = NULL; - aoOutput = NULL; + int i; + + for(i = 0; i < audioOutputArraySize; i++) { + finishAudioOutput(audioOutputArray[i]); + } + + free(audioOutputArray); + audioOutputArray = NULL; + audioOutputArraySize = 0; } int isCurrentAudioFormat(AudioFormat * audioFormat) { @@ -160,29 +183,65 @@ int isCurrentAudioFormat(AudioFormat * audioFormat) { } int openAudioDevice(AudioFormat * audioFormat) { - if(!aoOutput->open || !isCurrentAudioFormat(audioFormat)) { - if(audioFormat) copyAudioFormat(&audio_format, audioFormat); - if(shoutOutput) openAudioOutput(shoutOutput, &audio_format); - return openAudioOutput(aoOutput, &audio_format); + int isCurrentFormat = isCurrentAudioFormat(audioFormat); + int ret = -1; + int i; + + if(!audioOutputArray) return -1; + + if(!isCurrentFormat) { + copyAudioFormat(&audio_format, audioFormat); } - return 0; + for(i = 0; i < audioOutputArraySize; i++) { + if(!audioOutputArray[i]->open || !isCurrentFormat) { + if(0 == openAudioOutput(audioOutputArray[i], + &audio_format)) + { + ret = 0; + } + } + } + + return ret; } int playAudio(char * playChunk, int size) { - if(shoutOutput) playAudioOutput(shoutOutput, playChunk, size); - return playAudioOutput(aoOutput, playChunk, size); + int ret = -1; + int i; + + for(i = 0; i < audioOutputArraySize; i++) { + if(0 == playAudioOutput(audioOutputArray[i], playChunk, size)) { + ret = 0; + } + } + + return ret; } int isAudioDeviceOpen() { - return aoOutput->open; + int ret = 0; + int i; + + for(i = 0; i < audioOutputArraySize; i++) { + ret |= audioOutputArray[i]->open; + } + + return ret; } void closeAudioDevice() { - if(shoutOutput) closeAudioOutput(shoutOutput); - closeAudioOutput(aoOutput); + int i; + + for(i = 0; i < audioOutputArraySize; i++) { + closeAudioOutput(audioOutputArray[i]); + } } void sendMetadataToAudioDevice(MpdTag * tag) { - if(shoutOutput) sendMetadataToAudioOutput(shoutOutput, tag); + int i; + + for(i = 0; i < audioOutputArraySize; i++) { + sendMetadataToAudioOutput(audioOutputArray[i], tag); + } } diff --git a/src/audioOutput.c b/src/audioOutput.c index d85b9d978..0175ed04f 100644 --- a/src/audioOutput.c +++ b/src/audioOutput.c @@ -1,6 +1,12 @@ -#include <audioOutput.h> +#include "audioOutput.h" -#include <list.h> +#include "list.h" +#include "log.h" + +#include <string.h> + +#define AUDIO_OUTPUT_TYPE "type" +#define AUDIO_OUTPUT_NAME "name" static List * audioOutputPluginList; @@ -21,13 +27,32 @@ void finishAudioOutputPlugins() { freeList(audioOutputPluginList); } -AudioOutput * newAudioOutput(char * name) { +#define getBlockParam(name, str) { \ + BlockParam * bp; \ + bp = getBlockParam(param, name); \ + if(bp == NULL) { \ + ERROR("couldn't find parameter \"%s\" in audio output " \ + "definition begining at %i\n", \ + name, param->line); \ + exit(EXIT_FAILURE); \ + } \ + str = bp->value; \ +} + +AudioOutput * newAudioOutput(ConfigParam * param) { AudioOutput * ret = NULL; void * data = NULL; + char * name = NULL; + char * type = NULL; + + getBlockParam(AUDIO_OUTPUT_NAME, name); + getBlockParam(AUDIO_OUTPUT_TYPE, type); - if(findInList(audioOutputPluginList, name, &data)) { + if(findInList(audioOutputPluginList, type, &data)) { AudioOutputPlugin * plugin = (AudioOutputPlugin *) data; ret = malloc(sizeof(AudioOutput)); + ret->name = strdup(name); + ret->type = strdup(type); ret->finishDriverFunc = plugin->finishDriverFunc; ret->openDeviceFunc = plugin->openDeviceFunc; ret->playFunc = plugin->playFunc; @@ -35,11 +60,16 @@ AudioOutput * newAudioOutput(char * name) { ret->sendMetdataFunc = plugin->sendMetdataFunc; ret->open = 0; - if(plugin->initDriverFunc(ret) != 0) { + if(plugin->initDriverFunc(ret, param) != 0) { free(ret); ret = NULL; } } + else { + ERROR("couldn't find audio output plugin for type \"%s\" at " + "line %i", type, param->line); + exit(EXIT_FAILURE); + } return ret; } diff --git a/src/audioOutput.h b/src/audioOutput.h index ec43e9e7c..49c7110f9 100644 --- a/src/audioOutput.h +++ b/src/audioOutput.h @@ -24,12 +24,14 @@ #include "mpd_types.h" #include "audio.h" #include "tag.h" +#include "conf.h" #define AUDIO_AO_DRIVER_DEFAULT "default" typedef struct _AudioOutput AudioOutput; -typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput); +typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput, + ConfigParam * param); typedef void (* AudioOutputFinishDriverFunc) (AudioOutput * audioOutput); @@ -46,6 +48,8 @@ typedef void (* AudioOutputSendMetadataFunc) (AudioOutput * audioOutput, struct _AudioOutput { int open; + char * name; + char * type; AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputOpenDeviceFunc openDeviceFunc; @@ -73,7 +77,7 @@ void finishAudioOutputPlugins(); void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); -AudioOutput * newAudioOutput(char * name); +AudioOutput * newAudioOutput(ConfigParam * param); int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat); int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size); void closeAudioOutput(AudioOutput * audioOutput); diff --git a/src/audioOutput_ao.c b/src/audioOutput_ao.c index 7c997c99e..60c4ea402 100644 --- a/src/audioOutput_ao.c +++ b/src/audioOutput_ao.c @@ -56,7 +56,9 @@ static void audioOutputAo_error() { } } -static int audioOutputAo_initDriver(AudioOutput * audioOutput) { +static int audioOutputAo_initDriver(AudioOutput * audioOutput, + ConfigParam * param) +{ ao_info * ai; char * dup; char * stk1; @@ -66,38 +68,51 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput) { char * value; char * test; AoData * ad = newAoData(); + BlockParam * blockParam; audioOutput->data = ad; - ad->writeSize = strtol((getConf())[CONF_AUDIO_WRITE_SIZE],&test,10); - if (*test!='\0') { - ERROR("\"%s\" is not a valid write size\n", - (getConf())[CONF_AUDIO_WRITE_SIZE]); - exit(EXIT_FAILURE); + if((blockParam = getBlockParam(param, "write_size"))) { + ad->writeSize = strtol(blockParam->value, &test, 10); + if (*test!='\0') { + ERROR("\"%s\" is not a valid write size at line %i\n", + blockParam->value, blockParam->line); + exit(EXIT_FAILURE); + } } + else ad->writeSize = 1024; if(driverInitCount == 0) { ao_initialize(); } driverInitCount++; - - if(strcmp(AUDIO_AO_DRIVER_DEFAULT,(getConf())[CONF_AO_DRIVER])==0) { + + blockParam = getBlockParam(param, "driver"); + + if(!blockParam || 0 == strcmp(blockParam->value,"default")) { ad->driverId = ao_default_driver_id(); } else if((ad->driverId = - ao_driver_id((getConf())[CONF_AO_DRIVER]))<0) { - ERROR("\"%s\" is not a valid ao driver\n", - (getConf())[CONF_AO_DRIVER]); + ao_driver_id(blockParam->value))<0) { + ERROR("\"%s\" is not a valid ao driver at line %i\n", + blockParam->value, blockParam->line); exit(EXIT_FAILURE); } if((ai = ao_driver_info(ad->driverId))==NULL) { - ERROR("problems getting ao_driver_info\n"); + ERROR("problems getting driver info for device defined at " + "line %i\n", param->line); ERROR("you may not have permission to the audio device\n"); exit(EXIT_FAILURE); } - dup = strdup((getConf())[CONF_AO_DRIVER_OPTIONS]); + blockParam = getBlockParam(param, "options"); + + if(blockParam) { + dup = strdup(blockParam->value); + } + else dup = strdup(""); + if(strlen(dup)) { stk1 = NULL; n1 = strtok_r(dup,";",&stk1); diff --git a/src/audioOutput_shout.c b/src/audioOutput_shout.c index 45ef00846..f41b57359 100644 --- a/src/audioOutput_shout.c +++ b/src/audioOutput_shout.c @@ -88,7 +88,16 @@ static void freeShoutData(ShoutData * sd) { free(sd); } -static int shout_initDriver(AudioOutput * audioOutput) { +#define checkBlockParam(name) { \ + blockParam = getBlockParam(param, name); \ + if(!blockParam) { \ + ERROR("no \"%s\" defined for shout device defined at line " \ + "%i\n", name, param->line); \ + exit(EXIT_FAILURE); \ + } \ +} + +static int shout_initDriver(AudioOutput * audioOutput, ConfigParam * param) { ShoutData * sd; char * test; int port; @@ -97,73 +106,50 @@ static int shout_initDriver(AudioOutput * audioOutput) { char * passwd; char * user; char * name; - - if(!getConf()[CONF_SHOUT_HOST]) { - return -1; - } + BlockParam * blockParam; sd = newShoutData(); - if(!getConf()[CONF_SHOUT_MOUNT]) { - ERROR("shout host defined but not shout mount point\n"); - exit(EXIT_FAILURE); - } - - if(!getConf()[CONF_SHOUT_PORT]) { - ERROR("shout host defined but not shout port\n"); - exit(EXIT_FAILURE); - } + checkBlockParam("host"); + host = blockParam->value; - if(!getConf()[CONF_SHOUT_PASSWD]) { - ERROR("shout host defined but not shout password\n"); - exit(EXIT_FAILURE); - } + checkBlockParam("mount"); + mount = blockParam->value; - if(!getConf()[CONF_SHOUT_NAME]) { - ERROR("shout host defined but not shout name\n"); - exit(EXIT_FAILURE); - } + checkBlockParam("port"); - if(!getConf()[CONF_SHOUT_USER]) { - ERROR("shout host defined but not shout user\n"); - exit(EXIT_FAILURE); - } + port = strtol(blockParam->value, &test, 10); - if(!getConf()[CONF_SHOUT_QUALITY]) { - ERROR("shout host defined but not shout quality\n"); + if(*test != '\0' || port <= 0) { + ERROR("shout port \"%s\" is not a positive integer, line %i\n", + blockParam->value, blockParam->line); exit(EXIT_FAILURE); } - if(!getConf()[CONF_SHOUT_FORMAT]) { - ERROR("shout host defined but not shout format\n"); - exit(EXIT_FAILURE); - } + checkBlockParam("password"); + passwd = blockParam->value; - host = getConf()[CONF_SHOUT_HOST]; - passwd = getConf()[CONF_SHOUT_PASSWD]; - user = getConf()[CONF_SHOUT_USER]; - mount = getConf()[CONF_SHOUT_MOUNT]; - name = getConf()[CONF_SHOUT_NAME]; + checkBlockParam("name"); + name = blockParam->value; - port = strtol(getConf()[CONF_SHOUT_PORT], &test, 10); + checkBlockParam("user"); + user = blockParam->value; - if(*test != '\0' || port <= 0) { - ERROR("shout port \"%s\" is not a positive integer\n", - getConf()[CONF_SHOUT_PORT]); - exit(EXIT_FAILURE); - } + checkBlockParam("quality"); - sd->quality = strtod(getConf()[CONF_SHOUT_QUALITY], &test); + sd->quality = strtod(blockParam->value, &test); if(*test != '\0' || sd->quality < 0.0 || sd->quality > 10.0) { ERROR("shout quality \"%s\" is not a number in the range " - "0-10\n", getConf()[CONF_SHOUT_QUALITY]); + "0-10, line %i\n", blockParam->value, + blockParam->line); exit(EXIT_FAILURE); } - if(0 != parseAudioConfig(&(sd->outAudioFormat), - getConf()[CONF_SHOUT_FORMAT]) ) - { + checkBlockParam("format"); + + if(0 != parseAudioConfig(&(sd->outAudioFormat), blockParam->value)) { + ERROR("error parsing format at line %i\n", blockParam->line); exit(EXIT_FAILURE); } @@ -276,7 +262,7 @@ static int initEncoder(ShoutData * sd) { vorbis_info_init(&(sd->vi)); if( 0 != vorbis_encode_init_vbr(&(sd->vi), sd->outAudioFormat.channels, - sd->outAudioFormat.sampleRate, sd->quality) ) + sd->outAudioFormat.sampleRate, sd->quality/10.0) ) { ERROR("problem seting up vorbis encoder for shout\n"); vorbis_info_clear(&(sd->vi)); diff --git a/src/conf.c b/src/conf.c index a89a1e334..ccbb99f1c 100644 --- a/src/conf.c +++ b/src/conf.c @@ -22,8 +22,7 @@ #include "utils.h" #include "buffer2array.h" -#include "audio.h" -#include "volume.h" +#include "list.h" #include <sys/param.h> #include <stdio.h> @@ -35,270 +34,385 @@ #define MAX_STRING_SIZE MAXPATHLEN+80 -#define CONF_COMMENT '#' - -#define CONF_NUMBER_OF_PARAMS 43 -#define CONF_NUMBER_OF_PATHS 6 -#define CONF_NUMBER_OF_REQUIRED 5 -#define CONF_NUMBER_OF_ALLOW_CATS 1 - -#define CONF_CONNECTION_TIMEOUT_DEFAULT "60" -#define CONF_MAX_CONNECTIONS_DEFAULT "5" -#define CONF_MAX_PLAYLIST_LENGTH_DEFAULT "16384" -#define CONF_BUFFER_BEFORE_PLAY_DEFAULT "25%" -#define CONF_MAX_COMMAND_LIST_SIZE_DEFAULT "2048" -#define CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT "2048" -#define CONF_AO_DRIVER_DEFAULT AUDIO_AO_DRIVER_DEFAULT -#define CONF_AO_DRIVER_OPTIONS_DEFAULT "" -#define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT "no" -#define CONF_BIND_TO_ADDRESS_DEFAULT "any" -#define CONF_USER_DEFAULT "" -#define CONF_LOG_LEVEL_DEFAULT "default" -#define CONF_AUDIO_WRITE_SIZE_DEFAULT "1024" -#define CONF_BUFFER_SIZE_DEFAULT "2048" -#ifndef NO_OSS_MIXER -#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_OSS -#define CONF_MIXER_DEVICE_DEFAULT "" -#else -#ifdef HAVE_ALSA -#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_ALSA -#define CONF_MIXER_DEVICE_DEFAULT "" -#else -#define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_SOFTWARE -#define CONF_MIXER_DEVICE_DEFAULT "" -#endif -#endif - -static char * conf_params[CONF_NUMBER_OF_PARAMS]; +#define CONF_COMMENT '#' +#define CONF_BLOCK_BEGIN "{" +#define CONF_BLOCK_END "}" -void initConf() { +#define CONF_REPEATABLE_MASK 0x01 +#define CONF_BLOCK_MASK 0x02 + +typedef struct _configEntry { + unsigned char mask; + List * configParamList; +} ConfigEntry; + +static List * configEntriesList = NULL; + +static ConfigParam * newConfigParam(char * value, int line) { + ConfigParam * ret = malloc(sizeof(ConfigParam)); + + if(!value) ret->value = NULL; + else ret->value = strdup(value); + + ret->line = line; + + ret->numberOfBlockParams = 0; + ret->blockParams = NULL; + + return ret; +} + +static void freeConfigParam(ConfigParam * param) { int i; - for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) conf_params[i] = NULL; - - /* we don't specify these on the command line */ - conf_params[CONF_CONNECTION_TIMEOUT] = strdup(CONF_CONNECTION_TIMEOUT_DEFAULT); - conf_params[CONF_MIXER_DEVICE] = strdup(CONF_MIXER_DEVICE_DEFAULT); - conf_params[CONF_MAX_CONNECTIONS] = strdup(CONF_MAX_CONNECTIONS_DEFAULT); - conf_params[CONF_MAX_PLAYLIST_LENGTH] = strdup(CONF_MAX_PLAYLIST_LENGTH_DEFAULT); - conf_params[CONF_BUFFER_BEFORE_PLAY] = strdup(CONF_BUFFER_BEFORE_PLAY_DEFAULT); - conf_params[CONF_MAX_COMMAND_LIST_SIZE] = strdup(CONF_MAX_COMMAND_LIST_SIZE_DEFAULT); - conf_params[CONF_MAX_OUTPUT_BUFFER_SIZE] = strdup(CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT); - conf_params[CONF_AO_DRIVER] = strdup(CONF_AO_DRIVER_DEFAULT); - conf_params[CONF_AO_DRIVER_OPTIONS] = strdup(CONF_AO_DRIVER_OPTIONS_DEFAULT); - conf_params[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS] = strdup(CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT); - conf_params[CONF_BIND_TO_ADDRESS] = strdup(CONF_BIND_TO_ADDRESS_DEFAULT); - conf_params[CONF_MIXER_TYPE] = strdup(CONF_MIXER_TYPE_DEFAULT); - conf_params[CONF_USER] = strdup(CONF_USER_DEFAULT); - conf_params[CONF_LOG_LEVEL] = strdup(CONF_LOG_LEVEL_DEFAULT); - conf_params[CONF_AUDIO_WRITE_SIZE] = strdup(CONF_AUDIO_WRITE_SIZE_DEFAULT); - conf_params[CONF_BUFFER_SIZE] = strdup(CONF_BUFFER_SIZE_DEFAULT); + if(param->value) free(param->value); + + for(i=0; i<param->numberOfBlockParams; i++) { + if(param->blockParams[i].name) { + free(param->blockParams[i].name); + } + if(param->blockParams[i].value) { + free(param->blockParams[i].value); + } + } + + if(param->numberOfBlockParams) free(param->blockParams); + + free(param); } -char ** readConf(char * file) { - char * conf_strings[CONF_NUMBER_OF_PARAMS] = { - "port", - "music_directory", - "playlist_directory", - "log_file", - "error_file", - "connection_timeout", - "mixer_device", - "max_connections", - "max_playlist_length", - "buffer_before_play", - "max_command_list_size", - "max_output_buffer_size", - "ao_driver", - "ao_driver_options", - "save_absolute_paths_in_playlists", - "bind_to_address", - "mixer_type", - "state_file", - "user", - "db_file", - "log_level", - "mixer_control", - "audio_write_size", - "filesystem_charset", - "password", - "default_permissions", - "audio_buffer_size", - "replaygain", - "audio_output_format", - "http_proxy_host", - "http_proxy_port", - "http_proxy_user", - "http_proxy_password", - "replaygain_preamp", - "shout_host", - "shout_port", - "shout_password", - "shout_mount", - "shout_name", - "shout_user", - "shout_quality", - "id3v1_encoding", - "shout_format" - }; - - int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = { - CONF_MUSIC_DIRECTORY, - CONF_PLAYLIST_DIRECTORY, - CONF_LOG_FILE, - CONF_ERROR_FILE, - CONF_STATE_FILE, - CONF_DB_FILE - }; - - int conf_required[CONF_NUMBER_OF_REQUIRED] = { - CONF_MUSIC_DIRECTORY, - CONF_PLAYLIST_DIRECTORY, - CONF_LOG_FILE, - CONF_ERROR_FILE, - CONF_PORT - }; - - short conf_allowCat[CONF_NUMBER_OF_ALLOW_CATS] = { - CONF_PASSWORD - }; +ConfigEntry * newConfigEntry(int repeatable, int block) { + ConfigEntry * ret = malloc(sizeof(ConfigEntry)); + ret->mask = 0; + ret->configParamList = makeList((ListFreeDataFunc *)freeConfigParam); + + if(repeatable) ret->mask |= CONF_REPEATABLE_MASK; + if(block) ret->mask |= CONF_BLOCK_MASK; + + return ret; +} + +void freeConfigEntry(ConfigEntry * entry) { + freeList(entry->configParamList); + free(entry); +} + +void registerConfigParam(char * name, int repeatable, int block) { + ConfigEntry * entry; + + if(findInList(configEntriesList, name, NULL)) { + ERROR("config parameter \"%s\" already registered\n", name); + exit(EXIT_FAILURE); + } + + entry = newConfigEntry(repeatable, block); + + insertInList(configEntriesList, name, entry); +} + +void initConf() { + configEntriesList = makeList((ListFreeDataFunc *)freeConfigEntry); + + registerConfigParam(CONF_PORT, 0, 0); + registerConfigParam(CONF_MUSIC_DIR, 0, 0); + registerConfigParam(CONF_PLAYLIST_DIR, 0, 0); + registerConfigParam(CONF_LOG_FILE, 0, 0); + registerConfigParam(CONF_ERROR_FILE, 0, 0); + registerConfigParam(CONF_CONN_TIMEOUT, 0, 0); + registerConfigParam(CONF_MIXER_DEVICE, 0, 0); + registerConfigParam(CONF_MAX_CONN, 0, 0); + registerConfigParam(CONF_MAX_PLAYLIST_LENGTH, 0, 0); + registerConfigParam(CONF_BUFFER_BEFORE_PLAY, 0, 0); + registerConfigParam(CONF_MAX_COMMAND_LIST_SIZE, 0, 0); + registerConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE, 0, 0); + registerConfigParam(CONF_AUDIO_OUTPUT, 1, 1); + registerConfigParam(CONF_SAVE_ABSOLUTE_PATHS, 0, 0); + registerConfigParam(CONF_BIND_TO_ADDRESS, 1, 0); + registerConfigParam(CONF_MIXER_TYPE, 0, 0); + registerConfigParam(CONF_STATE_FILE, 0, 0); + registerConfigParam(CONF_USER, 0, 0); + registerConfigParam(CONF_DB_FILE, 0, 0); + registerConfigParam(CONF_LOG_LEVEL, 0, 0); + registerConfigParam(CONF_MIXER_CONTROL, 0, 0); + registerConfigParam(CONF_AUDIO_WRITE_SIZE, 0, 0); + registerConfigParam(CONF_FS_CHARSET, 0, 0); + registerConfigParam(CONF_PASSWORD, 1, 0); + registerConfigParam(CONF_DEFAULT_PERMS, 0, 0); + registerConfigParam(CONF_AUDIO_BUFFER_SIZE, 0, 0); + registerConfigParam(CONF_REPLAYGAIN, 0, 0); + registerConfigParam(CONF_AUDIO_OUTPUT_FORMAT, 0, 0); + registerConfigParam(CONF_HTTP_PROXY_HOST, 0, 0); + registerConfigParam(CONF_HTTP_PROXY_PORT, 0, 0); + registerConfigParam(CONF_HTTP_PROXY_USER, 0, 0); + registerConfigParam(CONF_HTTP_PROXY_PASSWORD, 0, 0); + registerConfigParam(CONF_REPLAYGAIN_PREAMP, 0, 0); + registerConfigParam(CONF_ID3V1_ENCODING, 0, 0); +} + +static void addBlockParam(ConfigParam * param, char * name, char * value, + int line) +{ + param->numberOfBlockParams++; + + param->blockParams = realloc(param->blockParams, + param->numberOfBlockParams*sizeof(BlockParam)); + + param->blockParams[param->numberOfBlockParams-1].name = strdup(name); + param->blockParams[param->numberOfBlockParams-1].value = strdup(value); + param->blockParams[param->numberOfBlockParams-1].line = line; +} + +static ConfigParam * readConfigBlock(FILE * fp, int * count, char * string) { + ConfigParam * ret = newConfigParam(NULL, *count); + + char ** array; + int i; + int numberOfArgs; + int argsMinusComment; + + while(myFgets(string, MAX_STRING_SIZE ,fp)) { + (*count)++; + + numberOfArgs = buffer2array(string, &array); + + for(i=0; i<numberOfArgs; i++) { + if(array[i][0] == CONF_COMMENT) break; + } + + argsMinusComment = i; + + if(0 == argsMinusComment) continue; + + if(1 == argsMinusComment && + 0 == strcmp(array[0], CONF_BLOCK_END)) + { + break; + } + + if(2 != argsMinusComment) { + ERROR("improperly formated config file at line %i:" + " %s\n", count, string); + exit(EXIT_FAILURE); + } + + if(0 == strcmp(array[0], CONF_BLOCK_BEGIN) || + 0 == strcmp(array[1], CONF_BLOCK_BEGIN) || + 0 == strcmp(array[0], CONF_BLOCK_END) || + 0 == strcmp(array[1], CONF_BLOCK_END)) + { + ERROR("improperly formated config file at line %i:" + " %s\n", count, string); + ERROR("in block begging at line %i\n", ret->line); + exit(EXIT_FAILURE); + } + + addBlockParam(ret, array[0], array[1], *count); + + freeArgArray(array, numberOfArgs); + } + + return ret; +} + +void readConf(char * file) { FILE * fp; char string[MAX_STRING_SIZE+1]; char ** array; int i; int numberOfArgs; - short allowCat[CONF_NUMBER_OF_PARAMS]; + int argsMinusComment; int count = 0; - - for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) allowCat[i] = 0; - - for(i=0;i<CONF_NUMBER_OF_ALLOW_CATS;i++) allowCat[conf_allowCat[i]] = 1; + ConfigEntry * entry; + void * voidPtr; + ConfigParam * param; if(!(fp=fopen(file,"r"))) { ERROR("problems opening file %s for reading\n",file); exit(EXIT_FAILURE); } - while(myFgets(string,sizeof(string),fp)) { + while(myFgets(string, MAX_STRING_SIZE, fp)) { count++; - if(string[0]==CONF_COMMENT) continue; - numberOfArgs = buffer2array(string,&array); - if(numberOfArgs==0) continue; - if(2!=numberOfArgs) { - ERROR("improperly formated config file at line %i: %s\n",count,string); + numberOfArgs = buffer2array(string, &array); + + for(i=0; i<numberOfArgs; i++) { + if(array[i][0] == CONF_COMMENT) break; + } + + argsMinusComment = i; + + if(0 == argsMinusComment) continue; + + if(2 != argsMinusComment) { + ERROR("improperly formated config file at line %i:" + " %s\n", count, string); exit(EXIT_FAILURE); } - i = 0; - while(i<CONF_NUMBER_OF_PARAMS && 0!=strcmp(conf_strings[i],array[0])) i++; - if(i>=CONF_NUMBER_OF_PARAMS) { - ERROR("unrecognized paramater in conf at line %i: %s\n",count,string); + + if(!findInList(configEntriesList, array[0], &voidPtr)) { + ERROR("unrecognized paramater in config file at line " + "%i: %s\n", count, string); exit(EXIT_FAILURE); } - - if(conf_params[i]!=NULL) { - if(allowCat[i]) { - conf_params[i] = realloc(conf_params[i], - strlen(conf_params[i])+ - strlen(CONF_CAT_CHAR)+ - strlen(array[1])+1); - strcat(conf_params[i],CONF_CAT_CHAR); - strcat(conf_params[i],array[1]); - } - else { - free(conf_params[i]); - conf_params[i] = strdup(array[1]); + + entry = (ConfigEntry *) voidPtr; + + if( !(entry->mask & CONF_REPEATABLE_MASK) && + entry->configParamList->numberOfNodes) + { + param = entry->configParamList->firstNode->data; + ERROR("config paramter \"%s\" is first defined on line " + "%i and redefined on line %i\n", + array[0], param->line, count); + exit(EXIT_FAILURE); + } + + if(entry->mask & CONF_BLOCK_MASK) { + if(0 != strcmp(array[1], CONF_BLOCK_BEGIN)) { + ERROR("improperly formated config file at " + "line %i: %s\n", count, string); + exit(EXIT_FAILURE); } + param = readConfigBlock(fp, &count, string); } - else conf_params[i] = strdup(array[1]); - free(array[0]); - free(array[1]); - free(array); + else param = newConfigParam(array[1], count); + + insertInListWithoutKey(entry->configParamList, param); + + freeArgArray(array, numberOfArgs); } +} - fclose(fp); +ConfigParam * getNextConfigParam(char * name, ConfigParam * last) { + void * voidPtr; + ConfigEntry * entry; + ListNode * node; + ConfigParam * param; - for(i=0;i<CONF_NUMBER_OF_REQUIRED;i++) { - if(conf_params[conf_required[i]] == NULL) { - ERROR("%s is unassigned in conf file\n", - conf_strings[conf_required[i]]); - exit(EXIT_FAILURE); + if(!findInList(configEntriesList, name, &voidPtr)) return NULL; + + entry = voidPtr; + + node = entry->configParamList->firstNode; + + if(last) { + while(node!=NULL) { + param = node->data; + node = node->nextNode; + if(param == last) break; } } - for(i=0;i<CONF_NUMBER_OF_PATHS;i++) { - if(conf_params[conf_absolutePaths[i]] && - conf_params[conf_absolutePaths[i]][0]!='/' && - conf_params[conf_absolutePaths[i]][0]!='~') - { - ERROR("\"%s\" is not an absolute path\n", - conf_params[conf_absolutePaths[i]]); - exit(EXIT_FAILURE); + if(node == NULL) return NULL; + + param = node->data; + + return param; +} + +char * getConfigParamValue(char * name) { + ConfigParam * param = getConfigParam(name); + + if(!param) return NULL; + + return param->value; +} + +char * forceAndGetConfigParamValue(char * name) { + ConfigParam * param = getConfigParam(name); + + if(!param) { + ERROR("\"%s\" not found in config file\n", name); + exit(EXIT_FAILURE); + } + + return param->value; +} + +BlockParam * getBlockParam(ConfigParam * param, char * name) { + BlockParam * ret = NULL; + int i; + + for(i = 0; i < param->numberOfBlockParams; i++) { + if(0 == strcmp(name, param->blockParams[i].name)) { + if(ret) { + ERROR("\"%s\" first defined on line %i, and " + "redefined on line %i\n", name, + ret->line, param->blockParams[i].line); + } + ret = param->blockParams+i; } - /* Parse ~ in path */ - else if(conf_params[conf_absolutePaths[i]] && - conf_params[conf_absolutePaths[i]][0]=='~') - { - struct passwd * pwd = NULL; - char * path; - int pos = 1; - if(conf_params[conf_absolutePaths[i]][1]=='/' || - conf_params[conf_absolutePaths[i]][1]=='\0') - { - if(conf_params[CONF_USER] && - strlen(conf_params[CONF_USER])) - { - pwd = getpwnam( - conf_params[CONF_USER]); - if(!pwd) { - ERROR("no such user: %s\n", - conf_params[CONF_USER]); - exit(EXIT_FAILURE); - } - } - else { - uid_t uid = geteuid(); - if((pwd = getpwuid(uid)) == NULL) { - ERROR("problems getting passwd " - "entry " - "for current user\n"); - exit(EXIT_FAILURE); - } + } + + return ret; +} + +char * parseConfigFilePath(char * name, int force) { + ConfigParam * param = getConfigParam(name); + char * path; + + if(!param && force) { + ERROR("config parameter \"%s\" not found\n", name); + exit(EXIT_FAILURE); + } + + if(!param) return NULL; + + path = param->value; + + if(path[0] != '/' && path[0] != '~') { + ERROR("\"%s\" is not an absolute path at line %i\n", + param->value, param->line); + exit(EXIT_FAILURE); + } + // Parse ~ in path + else if(path[0] == '~') { + struct passwd * pwd = NULL; + char * newPath; + int pos = 1; + if(path[1]=='/' || path[1] == '\0') { + ConfigParam * userParam = getConfigParam(CONF_USER); + + if(userParam) { + pwd = getpwnam(userParam->value); + if(!pwd) { + ERROR("no such user %s at line %i\n", + userParam->value, + userParam->line); + exit(EXIT_FAILURE); } } else { - int foundSlash = 0; - char * ch = &( - conf_params[conf_absolutePaths[i]][1]); - for(;*ch!='\0' && *ch!='/';ch++); - if(*ch=='/') foundSlash = 1; - * ch = '\0'; - pos+= ch- - &(conf_params[ - conf_absolutePaths[i]][1]); - if((pwd = getpwnam(&(conf_params[ - conf_absolutePaths[i]][1]))) == NULL) - { - ERROR("user \"%s\" not found\n", - &(conf_params[ - conf_absolutePaths[i]][1])); + uid_t uid = geteuid(); + if((pwd = getpwuid(uid)) == NULL) { + ERROR("problems getting passwd entry " + "for current user\n"); exit(EXIT_FAILURE); } - if(foundSlash) *ch = '/'; } - path = malloc(strlen(pwd->pw_dir)+strlen( - &(conf_params[conf_absolutePaths[i]][pos]))+1); - strcpy(path,pwd->pw_dir); - strcat(path,&(conf_params[conf_absolutePaths[i]][pos])); - free(conf_params[conf_absolutePaths[i]]); - conf_params[conf_absolutePaths[i]] = path; } + else { + int foundSlash = 0; + char * ch = path+1; + for(;*ch!='\0' && *ch!='/';ch++); + if(*ch=='/') foundSlash = 1; + * ch = '\0'; + pos+= ch-path+1; + if((pwd = getpwnam(path+1)) == NULL) { + ERROR("user \"%s\" not found at line %i\n", + path+1, param->line); + exit(EXIT_FAILURE); + } + if(foundSlash) *ch = '/'; + } + newPath = malloc(strlen(pwd->pw_dir)+strlen(path+pos)+1); + strcpy(newPath, pwd->pw_dir); + strcat(newPath, path+pos); + free(param->value); + param->value = newPath; } - return conf_params; -} - -char ** getConf() { - return conf_params; + return param->value; } diff --git a/src/conf.h b/src/conf.h index f6bd5d283..1c9413654 100644 --- a/src/conf.h +++ b/src/conf.h @@ -21,59 +21,72 @@ #include "../config.h" -#define CONF_PORT 0 -#define CONF_MUSIC_DIRECTORY 1 -#define CONF_PLAYLIST_DIRECTORY 2 -#define CONF_LOG_FILE 3 -#define CONF_ERROR_FILE 4 -#define CONF_CONNECTION_TIMEOUT 5 -#define CONF_MIXER_DEVICE 6 -#define CONF_MAX_CONNECTIONS 7 -#define CONF_MAX_PLAYLIST_LENGTH 8 -#define CONF_BUFFER_BEFORE_PLAY 9 -#define CONF_MAX_COMMAND_LIST_SIZE 10 -#define CONF_MAX_OUTPUT_BUFFER_SIZE 11 -#define CONF_AO_DRIVER 12 -#define CONF_AO_DRIVER_OPTIONS 13 -#define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS 14 -#define CONF_BIND_TO_ADDRESS 15 -#define CONF_MIXER_TYPE 16 -#define CONF_STATE_FILE 17 -#define CONF_USER 18 -#define CONF_DB_FILE 19 -#define CONF_LOG_LEVEL 20 -#define CONF_MIXER_CONTROL 21 -#define CONF_AUDIO_WRITE_SIZE 22 -#define CONF_FS_CHARSET 23 -#define CONF_PASSWORD 24 -#define CONF_DEFAULT_PERMISSIONS 25 -#define CONF_BUFFER_SIZE 26 -#define CONF_REPLAYGAIN 27 -#define CONF_AUDIO_OUTPUT_FORMAT 28 -#define CONF_HTTP_PROXY_HOST 29 -#define CONF_HTTP_PROXY_PORT 30 -#define CONF_HTTP_PROXY_USER 31 -#define CONF_HTTP_PROXY_PASSWORD 32 -#define CONF_REPLAYGAIN_PREAMP 33 -#define CONF_SHOUT_HOST 34 -#define CONF_SHOUT_PORT 35 -#define CONF_SHOUT_PASSWD 36 -#define CONF_SHOUT_MOUNT 37 -#define CONF_SHOUT_NAME 38 -#define CONF_SHOUT_USER 39 -#define CONF_SHOUT_QUALITY 40 -#define CONF_ID3V1_ENCODING 41 -#define CONF_SHOUT_FORMAT 42 +#define CONF_PORT "port" +#define CONF_MUSIC_DIR "music_directory" +#define CONF_PLAYLIST_DIR "playlist_directory" +#define CONF_LOG_FILE "log_file" +#define CONF_ERROR_FILE "error_file" +#define CONF_CONN_TIMEOUT "connection_timeout" +#define CONF_MIXER_DEVICE "mixer_device" +#define CONF_MAX_CONN "max_connections" +#define CONF_MAX_PLAYLIST_LENGTH "max_playlist_length" +#define CONF_BUFFER_BEFORE_PLAY "buffer_before_play" +#define CONF_MAX_COMMAND_LIST_SIZE "max_command_list_size" +#define CONF_MAX_OUTPUT_BUFFER_SIZE "max_output_buffer_size" +#define CONF_AUDIO_OUTPUT "audio_output" +#define CONF_SAVE_ABSOLUTE_PATHS "save_absolute_paths_in_playlists" +#define CONF_BIND_TO_ADDRESS "bind_to_address" +#define CONF_MIXER_TYPE "mixer_type" +#define CONF_STATE_FILE "state_file" +#define CONF_USER "user" +#define CONF_DB_FILE "db_file" +#define CONF_LOG_LEVEL "log_level" +#define CONF_MIXER_CONTROL "mixer_control" +#define CONF_AUDIO_WRITE_SIZE "audio_write_size" +#define CONF_FS_CHARSET "filesystem_charset" +#define CONF_PASSWORD "password" +#define CONF_DEFAULT_PERMS "default_permissions" +#define CONF_AUDIO_BUFFER_SIZE "audio_buffer_size" +#define CONF_REPLAYGAIN "replaygain" +#define CONF_AUDIO_OUTPUT_FORMAT "audio_output_format" +#define CONF_HTTP_PROXY_HOST "http_proxy_host" +#define CONF_HTTP_PROXY_PORT "http_proxy_port" +#define CONF_HTTP_PROXY_USER "http_proxy_user" +#define CONF_HTTP_PROXY_PASSWORD "http_proxy_password" +#define CONF_REPLAYGAIN_PREAMP "replaygain_preamp" +#define CONF_ID3V1_ENCODING "id3v1_encoding" -#define CONF_CAT_CHAR "\n" +typedef struct _BlockParam { + char * name; + char * value; + int line; +} BlockParam; -/* do not free the return value, it is a static variable */ -char ** readConf(char * file); - -char ** getConf(); +typedef struct _ConfigParam { + char * value; + unsigned int line; + BlockParam * blockParams; + int numberOfBlockParams; +} ConfigParam; void initConf(); -void writeConf(char * file); +void readConf(char * file); + +/* don't free the returned value + set _last_ to NULL to get first entry */ +ConfigParam * getNextConfigParam(char * name, ConfigParam * last); + +#define getConfigParam(name) getNextConfigParam(name, NULL) + +char * getConfigParamValue(char * name); + +char * forceAndGetConfigParamValue(char * name); + +void registerConfigParam(char * name, int repeats, int block); + +BlockParam * getBlockParam(ConfigParam * param, char * name); + +char * parseConfigFilePath(char * name, int force); #endif diff --git a/src/directory.c b/src/directory.c index b5c5ed965..85773489b 100644 --- a/src/directory.c +++ b/src/directory.c @@ -1053,7 +1053,8 @@ int readDirectoryDB() { fsCharset = &(buffer[strlen( DIRECTORY_FS_CHARSET)]); if((tempCharset = - getConf()[CONF_FS_CHARSET]) && + getConfigParamValue( + CONF_FS_CHARSET)) && strcmp(fsCharset,tempCharset)) { WARNING("Using \"%s\" for the " diff --git a/src/inputStream_http.c b/src/inputStream_http.c index 353285ebd..15768929f 100644 --- a/src/inputStream_http.c +++ b/src/inputStream_http.c @@ -47,6 +47,11 @@ #define HTTP_REDIRECT_MAX 10 +static char * proxyHost = NULL; +static int proxyPort = 0; +static char * proxyUser = NULL; +static char * proxyPassword = NULL; + typedef struct _InputStreemHTTPData { char * host; char * path; @@ -59,57 +64,73 @@ typedef struct _InputStreemHTTPData { int icyMetaint; int prebuffer; int icyOffset; - char * proxyHost; - int proxyPort; char * proxyAuth; char * httpAuth; } InputStreamHTTPData; void inputStream_initHttp() { - if(getConf()[CONF_HTTP_PROXY_HOST]) { - char * portStr = getConf()[CONF_HTTP_PROXY_PORT]; - int port = 0; - char * test; - - if(!portStr) { - ERROR("http_proxy_host specified but not the http_" - "proxy_port\n"); + ConfigParam * param = getConfigParam(CONF_HTTP_PROXY_HOST); + char * test; + + if(param) { + proxyHost = param->value; + + param = getConfigParam(CONF_HTTP_PROXY_PORT); + + if(!param) { + ERROR("%s specified but not %s", CONF_HTTP_PROXY_HOST, + CONF_HTTP_PROXY_PORT); exit(EXIT_FAILURE); } - port = strtol(portStr, &test, 10); - if(port <= 0 || *test != '\0') { - ERROR("http_proxy_port \"%s\" is not a positive integer" - "\n", portStr); + proxyPort = strtol(param->value, &test, 10); + if(proxyPort <= 0 || *test != '\0') { + ERROR("%s \"%s\" is not a positive integer, line %i\n" + CONF_HTTP_PROXY_PORT, param->value, + param->line); } - if(getConf()[CONF_HTTP_PROXY_USER] && - !getConf()[CONF_HTTP_PROXY_PASSWORD]) - { - ERROR("http_proxy_user specified, but not http_proxy_" - "password\n"); - exit(EXIT_FAILURE); + param = getConfigParam(CONF_HTTP_PROXY_USER); + + if(param) { + proxyUser = param->value; + + param = getConfigParam(CONF_HTTP_PROXY_PASSWORD); + + if(!param) { + ERROR("%s specifid but not %s\n", + CONF_HTTP_PROXY_USER, + CONF_HTTP_PROXY_PASSWORD); + exit(EXIT_FAILURE); + } + + proxyPassword = param->value; } - if(getConf()[CONF_HTTP_PROXY_PASSWORD] && - !getConf()[CONF_HTTP_PROXY_USER]) - { - ERROR("http proxy password specified, but not http " - "proxy user\n"); + param = getConfigParam(CONF_HTTP_PROXY_PASSWORD); + + if(param) { + ERROR("%s specifid but not %s\n", + CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER); exit(EXIT_FAILURE); } } - else if(getConf()[CONF_HTTP_PROXY_PORT]) { - ERROR("http_proxy_port specified but not http_proxy_host\n"); + else if((param = getConfigParam(CONF_HTTP_PROXY_PORT))) { + ERROR("%s specified but not %s, line %i\n", + CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST, + param->line); exit(EXIT_FAILURE); } - else if(getConf()[CONF_HTTP_PROXY_USER]) { - ERROR("http_proxy_user specified but not http_proxy_host\n"); + else if((param = getConfigParam(CONF_HTTP_PROXY_USER))) { + ERROR("%s specified but not %s, line %i\n", + CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST, + param->line); exit(EXIT_FAILURE); } - else if(getConf()[CONF_HTTP_PROXY_PASSWORD]) { - ERROR("http_proxy_password specified but not http_proxy_host" - "\n"); + else if((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) { + ERROR("%s specified but not %s, line %i\n", + CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST, + param->line); exit(EXIT_FAILURE); } } @@ -188,19 +209,10 @@ static char * authString(char * header, char * user, char * password) { static InputStreamHTTPData * newInputStreamHTTPData() { InputStreamHTTPData * ret = malloc(sizeof(InputStreamHTTPData)); - if(getConf()[CONF_HTTP_PROXY_HOST]) { - ret->proxyHost = getConf()[CONF_HTTP_PROXY_HOST]; - DEBUG(__FILE__ ": Proxy host %s\n", ret->proxyHost); - ret->proxyPort = atoi(getConf()[CONF_HTTP_PROXY_PORT]); - DEBUG(__FILE__ ": Proxy port %i\n", ret->proxyPort); - ret->proxyAuth = proxyAuthString( - getConf()[CONF_HTTP_PROXY_USER], - getConf()[CONF_HTTP_PROXY_PASSWORD]); - } - else { - ret->proxyHost = NULL; - ret->proxyAuth = NULL; + if(proxyHost) { + ret->proxyAuth = proxyAuthString(proxyUser, proxyPassword); } + else ret->proxyAuth = NULL; ret->httpAuth = NULL; ret->host = NULL; @@ -299,7 +311,7 @@ static int parseUrl(InputStreamHTTPData * data, char * url) { } /* fetch the path */ - if(data->proxyHost) data->path = strdup(url); + if(proxyHost) data->path = strdup(url); else data->path = strdup(slash ? slash : "/"); return 0; @@ -319,9 +331,9 @@ static int initHTTPConnection(InputStream * inStream) { struct sockaddr_in6 sin6; #endif - if(data->proxyHost) { - connHost = data->proxyHost; - connPort = data->proxyPort; + if(proxyHost) { + connHost = proxyHost; + connPort = proxyPort; } else { connHost = data->host; diff --git a/src/interface.c b/src/interface.c index 196ff7706..4282b89be 100644 --- a/src/interface.c +++ b/src/interface.c @@ -47,12 +47,18 @@ #define INTERFACE_LIST_MODE_BEGIN "command_list_begin" #define INTERFACE_LIST_OK_MODE_BEGIN "command_list_ok_begin" #define INTERFACE_LIST_MODE_END "command_list_end" -#define INTERFACE_DEFAULT_OUT_BUFFER_SIZE 4096 - -int interface_max_connections = 0; -int interface_timeout; -unsigned long long interface_max_command_list_size; -unsigned long long interface_max_output_buffer_size; +#define INTERFACE_DEFAULT_OUT_BUFFER_SIZE 4096 +#define INTERFACE_TIMEOUT_DEFAULT 60 +#define INTERFACE_MAX_CONNECTIONS_DEFAULT 10 +#define INTERFACE_MAX_COMMAND_LIST_DEFAULT (2048*1024) +#define INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (2048*1024) + +static int interface_max_connections = INTERFACE_MAX_CONNECTIONS_DEFAULT; +static int interface_timeout = INTERFACE_TIMEOUT_DEFAULT; +static size_t interface_max_command_list_size = + INTERFACE_MAX_COMMAND_LIST_DEFAULT; +static size_t interface_max_output_buffer_size = + INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT; typedef struct _Interface { char buffer[INTERFACE_MAX_BUFFER_LENGTH+2]; @@ -420,33 +426,58 @@ int doIOForInterfaces() { void initInterfaces() { int i; char * test; + ConfigParam * param; - interface_timeout = strtol((getConf())[CONF_CONNECTION_TIMEOUT],&test,10); - if(*test!='\0' || interface_timeout<=0) { - ERROR("connection timeout \"%s\" is not a positive integer\n",(getConf())[CONF_CONNECTION_TIMEOUT]); - exit(EXIT_FAILURE); - } + param = getConfigParam(CONF_CONN_TIMEOUT); - interface_max_connections = strtol((getConf())[CONF_MAX_CONNECTIONS],&test,10); - if(*test!='\0' || interface_max_connections<=0) { - ERROR("max connections \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_CONNECTIONS]); - exit(EXIT_FAILURE); + if(param) { + interface_timeout = strtol(param->value,&test,10); + if(*test!='\0' || interface_timeout<=0) { + ERROR("connection timeout \"%s\" is not a positive " + "integer, line %i\n", CONF_CONN_TIMEOUT, + param->line); + exit(EXIT_FAILURE); + } } - interface_max_command_list_size = strtoll((getConf())[CONF_MAX_COMMAND_LIST_SIZE],&test,10); - if(*test!='\0' || interface_max_command_list_size<=0) { - ERROR("max command list size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_COMMAND_LIST_SIZE]); - exit(EXIT_FAILURE); + param = getConfigParam(CONF_MAX_CONN); + + if(param) { + interface_max_connections = strtol(param->value, &test, 10); + if(*test!='\0' || interface_max_connections<=0) { + ERROR("max connections \"%s\" is not a positive integer" + ", line %i\n", param->value, param->line); + exit(EXIT_FAILURE); + } } - interface_max_output_buffer_size = strtoll((getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE],&test,10); - if(*test!='\0' || interface_max_output_buffer_size<=0) { - ERROR("max output buffer size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE]); - exit(EXIT_FAILURE); + param = getConfigParam(CONF_MAX_COMMAND_LIST_SIZE); + + if(param) { + interface_max_command_list_size = strtoll(param->value, + &test, 10); + if(*test!='\0' || interface_max_command_list_size<=0) { + ERROR("max command list size \"%s\" is not a positive " + "integer, line %i\n", param->value, + param->line); + exit(EXIT_FAILURE); + } + interface_max_command_list_size*=1024; } - interface_max_command_list_size*=1024; - interface_max_output_buffer_size*=1024; + param = getConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE); + + if(param) { + interface_max_output_buffer_size = strtoll(param->value, &test, + 10); + if(*test!='\0' || interface_max_output_buffer_size<=0) { + ERROR("max output buffer size \"%s\" is not a positive " + "integer, line %i\n", param->value, + param->line); + exit(EXIT_FAILURE); + } + interface_max_output_buffer_size*=1024; + } interfaces = malloc(sizeof(Interface)*interface_max_connections); diff --git a/src/list.c b/src/list.c index 68ec8d9c3..8faa271c0 100644 --- a/src/list.c +++ b/src/list.c @@ -192,7 +192,7 @@ int findInList(List * list,char * key,void ** data) { tmpNode = list->nodesArray[cur]; cmp = strcmp(tmpNode->key,key); if(cmp==0) { - (*data) = tmpNode->data; + if(data) *data = tmpNode->data; return 1; } else if(cmp>0) high = cur; diff --git a/src/list.h b/src/list.h index 7b08e7e51..9c879e91a 100644 --- a/src/list.h +++ b/src/list.h @@ -88,6 +88,7 @@ void deleteNodeFromList(List * list,ListNode * node); * _key_ -> which node is being searched for * _data_ -> a pointer to where data will be placed, * _data_ memory should not by allocated or freed + * _data_ can be NULL * returns 1 if successful, 0 otherwise */ int findInList(List * list, char * key, void ** data); diff --git a/src/listen.c b/src/listen.c index 49ff4c33e..065e1ccc6 100644 --- a/src/listen.c +++ b/src/listen.c @@ -44,6 +44,7 @@ int listenSocket; int establish(unsigned short port) { + ConfigParam * param; int allowReuse = ALLOW_REUSE; int sock; struct sockaddr * addrp; @@ -60,8 +61,10 @@ int establish(unsigned short port) { memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_port = htons(port); sin.sin_family = AF_INET; + + param = getConfigParam(CONF_BIND_TO_ADDRESS); - if(strcmp((getConf())[CONF_BIND_TO_ADDRESS],"any")==0) { + if(!param || 0==strcmp(param->value, "any")==0) { #ifdef HAVE_IPV6 if(ipv6Supported()) { sin6.sin6_addr = in6addr_any; @@ -78,9 +81,9 @@ int establish(unsigned short port) { } else { struct hostent * he; - if(!(he = gethostbyname((getConf())[CONF_BIND_TO_ADDRESS]))) { - ERROR("can't lookup host \"%s\"\n", - (getConf())[CONF_BIND_TO_ADDRESS]); + if(!(he = gethostbyname(param->value))) { + ERROR("can't lookup host \"%s\" at line %i\n", + param->value, param->line); exit(EXIT_FAILURE); } switch(he->h_addrtype) { @@ -88,8 +91,8 @@ int establish(unsigned short port) { case AF_INET6: if(!ipv6Supported()) { ERROR("no IPv6 support, but a IPv6 address " - "found for \"%s\"\n", - (getConf())[CONF_BIND_TO_ADDRESS]); + "found for \"%s\" at line %i\n", + param->value, param->line); exit(EXIT_FAILURE); } bcopy((char *)he->h_addr,(char *) @@ -105,8 +108,9 @@ int establish(unsigned short port) { addrlen = sizeof(struct sockaddr_in); break; default: - ERROR("address type for \"%s\" is not IPv4 or IPv6\n", - (getConf())[CONF_BIND_TO_ADDRESS]); + ERROR("address type for \"%s\" is not IPv4 or IPv6 " + "at line %i\n", + param->value, param->line); exit(EXIT_FAILURE); } } @@ -32,16 +32,24 @@ short warningFlushed = 0; static char * warningBuffer = NULL; void initLog() { - if(strcmp(getConf()[CONF_LOG_LEVEL],"default")==0) { + ConfigParam * param = getConfigParam(CONF_LOG_LEVEL); + + if(!param) return; + + if(0 == strcmp(param->value, "default")) { if(logLevel<LOG_LEVEL_LOW) logLevel = LOG_LEVEL_LOW; } - else if(strcmp(getConf()[CONF_LOG_LEVEL],"secure")==0) { + else if(0 == strcmp(param->value, "secure")) { if(logLevel<LOG_LEVEL_SECURE) logLevel = LOG_LEVEL_SECURE; } - else if(strcmp(getConf()[CONF_LOG_LEVEL],"verbose")==0) { + else if(0 == strcmp(param->value, "verbose")) { if(logLevel<LOG_LEVEL_DEBUG) logLevel = LOG_LEVEL_DEBUG; } - else ERROR("unknown log level \"%s\"\n",getConf()[CONF_LOG_LEVEL]); + else { + ERROR("unknown log level \"%s\" at line %i\n", + param->value, param->line); + exit(EXIT_FAILURE); + } } #define BUFFER_LENGTH 4096 diff --git a/src/main.c b/src/main.c index ddde281a7..f56d74939 100644 --- a/src/main.c +++ b/src/main.c @@ -165,9 +165,12 @@ void parseOptions(int argc, char ** argv, Options * options) { return; } else if(argcLeft<=2) { - char ** conf = NULL; - if(argcLeft==2) conf = readConf(argv[argc-1]); - if(argcLeft==1) { + int conf = 0; + if(argcLeft==2) { + readConf(argv[argc-1]); + conf = 1; + } + else if(argcLeft==1) { FILE * fp; char * homedir = getenv("HOME"); char userfile[MAXPATHLEN+1] = ""; @@ -179,23 +182,27 @@ void parseOptions(int argc, char ** argv, Options * options) { } if(strlen(userfile) && (fp=fopen(userfile,"r"))) { fclose(fp); - conf = readConf(userfile); + readConf(userfile); + conf = 1; } else if((fp=fopen(SYSTEM_CONFIG_FILE_LOCATION,"r"))) { fclose(fp); - conf = readConf(SYSTEM_CONFIG_FILE_LOCATION); + readConf(SYSTEM_CONFIG_FILE_LOCATION); + conf = 1; } } if(conf) { - options->portStr = conf[CONF_PORT]; - options->musicDirArg = conf[CONF_MUSIC_DIRECTORY]; - options->playlistDirArg = conf[CONF_PLAYLIST_DIRECTORY]; - options->logFile = conf[CONF_LOG_FILE]; - options->errorFile = conf[CONF_ERROR_FILE]; - options->usr = conf[CONF_USER]; - if(conf[CONF_DB_FILE]) { - options->dbFile = conf[CONF_DB_FILE]; - } + options->portStr = forceAndGetConfigParamValue( + CONF_PORT); + options->musicDirArg = + parseConfigFilePath(CONF_MUSIC_DIR, 1); + options->playlistDirArg = + parseConfigFilePath(CONF_PLAYLIST_DIR, 1); + options->logFile = parseConfigFilePath(CONF_LOG_FILE,1); + options->errorFile = + parseConfigFilePath(CONF_ERROR_FILE, 1); + options->usr = parseConfigFilePath(CONF_USER, 0); + options->dbFile = parseConfigFilePath(CONF_DB_FILE, 0); return; } } diff --git a/src/path.c b/src/path.c index 48d5eff09..1d599bda3 100644 --- a/src/path.c +++ b/src/path.c @@ -114,6 +114,7 @@ void initPaths(char * playlistDirArg, char * musicDirArg) { char * charset = NULL; char * originalLocale; struct stat st; + ConfigParam * param; playlistDir = prependCwdToPathDup(playlistDirArg); if((stat(playlistDir,&st))<0) { @@ -135,8 +136,10 @@ void initPaths(char * playlistDirArg, char * musicDirArg) { exit(EXIT_FAILURE); } - if(getConf()[CONF_FS_CHARSET]) { - charset = strdup(getConf()[CONF_FS_CHARSET]); + param = getConfigParam(CONF_FS_CHARSET); + + if(param) { + charset = strdup(param->value); } #ifdef HAVE_LOCALE #ifdef HAVE_LANGINFO_CODESET @@ -296,5 +299,3 @@ char * prependCwdToPathDup(char * path) { return realloc(ret,len+1); } - -/* vim:set shiftwidth=4 tabstop=8 expandtab: */ diff --git a/src/permission.c b/src/permission.c index e9e74ad7a..795fe577d 100644 --- a/src/permission.c +++ b/src/permission.c @@ -69,56 +69,53 @@ unsigned int parsePermissions(char * string) { } void initPermissions() { - char * passwordSets; - char * nextSet; char * temp; - char * cp1; char * cp2; char * password; unsigned int * permission; + ConfigParam * param; permission_passwords = makeList(free); permission_default = PERMISSION_READ | PERMISSION_ADD | PERMISSION_CONTROL | PERMISSION_ADMIN; - if(getConf()[CONF_DEFAULT_PERMISSIONS]) { - permission_default = parsePermissions( - getConf()[CONF_DEFAULT_PERMISSIONS]); - } - - if(!getConf()[CONF_PASSWORD]) return; - - if(!getConf()[CONF_DEFAULT_PERMISSIONS]) permission_default = 0; + param = getNextConfigParam(CONF_PASSWORD, NULL); - passwordSets = strdup(getConf()[CONF_PASSWORD]); + if(param) { + permission_default = 0; - nextSet = strtok_r(passwordSets,CONF_CAT_CHAR,&cp1); - while(nextSet && strlen(nextSet)) { - if(!strstr(nextSet,PERMISSION_PASSWORD_CHAR)) { - ERROR("\"%s\" not found in password string \"%s\"\n", + do { + if(!strstr(param->value, PERMISSION_PASSWORD_CHAR)) { + ERROR("\"%s\" not found in password string " + "\"%s\", line %i\n", PERMISSION_PASSWORD_CHAR, - nextSet); - exit(EXIT_FAILURE); - } + param->value, + param->line); + exit(EXIT_FAILURE); + } - if(!(temp = strtok_r(nextSet,PERMISSION_PASSWORD_CHAR,&cp2))) { - ERROR("something weird just happend in permission.c\n"); - exit(EXIT_FAILURE); - } - password = temp; + if(!(temp = strtok_r(param->value, + PERMISSION_PASSWORD_CHAR,&cp2))) { + ERROR("something weird just happend in permission.c\n"); + exit(EXIT_FAILURE); + } - permission = malloc(sizeof(unsigned int)); - *permission = parsePermissions(strtok_r(NULL,"",&cp2)); + + password = temp; - insertInList(permission_passwords,password,permission); + permission = malloc(sizeof(unsigned int)); + *permission = parsePermissions(strtok_r(NULL,"",&cp2)); - nextSet = strtok_r(NULL,CONF_CAT_CHAR,&cp1); + insertInList(permission_passwords,password,permission); + } while((param = getNextConfigParam(CONF_PASSWORD, param))); } - sortList(permission_passwords); + param = getConfigParam(CONF_DEFAULT_PERMS); - free(passwordSets); + if(param) permission_default = parsePermissions(param->value); + + sortList(permission_passwords); } int getPermissionFromPassword(char * password, unsigned int * permission) { diff --git a/src/playerData.c b/src/playerData.c index 5804f306c..b851a99f9 100644 --- a/src/playerData.c +++ b/src/playerData.c @@ -30,23 +30,32 @@ int buffered_before_play; int buffered_chunks; +#define DEFAULT_BUFFER_SIZE 2048 +#define DEFAULT_BUFFER_BEFORE_PLAY 25 + PlayerData * playerData_pd; void initPlayerData() { - float perc; + float perc = DEFAULT_BUFFER_BEFORE_PLAY; char * test; int shmid; int crossfade = 0; - size_t bufferSize; + size_t bufferSize = DEFAULT_BUFFER_SIZE; size_t allocationSize; OutputBuffer * buffer; + ConfigParam * param; - bufferSize = strtol(getConf()[CONF_BUFFER_SIZE],&test,10); - if(*test!='\0' || bufferSize<=0) { - ERROR("buffer size \"%s\" is not a positive integer\n", - getConf()[CONF_BUFFER_SIZE]); - exit(EXIT_FAILURE); + param = getConfigParam(CONF_AUDIO_BUFFER_SIZE); + + if(param) { + bufferSize = strtol(param->value, &test, 10); + if(*test!='\0' || bufferSize<=0) { + ERROR("buffer size \"%s\" is not a positive integer, " + "line %i\n", param->value, param->line); + exit(EXIT_FAILURE); + } } + bufferSize*=1024; buffered_chunks = bufferSize/CHUNK_SIZE; @@ -56,13 +65,18 @@ void initPlayerData() { exit(EXIT_FAILURE); } - perc = strtod((getConf())[CONF_BUFFER_BEFORE_PLAY],&test); - if(*test!='%' || perc<0 || perc>100) { - ERROR("buffered before play \"%s\" is not a positive " - "percentage and less than 100 percent\n", - (getConf())[CONF_BUFFER_BEFORE_PLAY]); - exit(EXIT_FAILURE); + param = getConfigParam(CONF_BUFFER_BEFORE_PLAY); + + if(param) { + perc = strtod(param->value, &test); + if(*test!='%' || perc<0 || perc>100) { + ERROR("buffered before play \"%s\" is not a positive " + "percentage and less than 100 percent, line %i" + "\n", param->value, param->line); + exit(EXIT_FAILURE); + } } + buffered_before_play = (perc/100)*buffered_chunks; if(buffered_before_play>buffered_chunks) { buffered_before_play = buffered_chunks; diff --git a/src/playlist.c b/src/playlist.c index fd1873f93..74bb56116 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -60,6 +60,9 @@ #define PLAYLIST_HASH_MULT 4 +#define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16) +#define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS 0 + typedef struct _Playlist { Song ** songs; /* holds version a song was modified on */ @@ -77,13 +80,13 @@ typedef struct _Playlist { static Playlist playlist; static int playlist_state = PLAYLIST_STATE_STOP; -static int playlist_max_length; +static int playlist_max_length = DEFAULT_PLAYLIST_MAX_LENGTH; static int playlist_stopOnError; static int playlist_errorCount = 0; static int playlist_queueError; static int playlist_noGoToNext = 0; -static int playlist_saveAbsolutePaths; +static int playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS; static char * playlist_stateFile = NULL; @@ -128,6 +131,7 @@ static void incrPlaylistCurrent() { void initPlaylist() { char * test; int i; + ConfigParam * param; playlist.length = 0; playlist.repeat = 0; @@ -136,26 +140,32 @@ void initPlaylist() { playlist.queued = -1; playlist.current = -1; - playlist_max_length = strtol((getConf())[CONF_MAX_PLAYLIST_LENGTH],&test,10); - if(*test!='\0') { - ERROR("max playlist length \"%s\" is not an integer\n", - (getConf())[CONF_MAX_PLAYLIST_LENGTH]); - exit(EXIT_FAILURE); - } + param = getConfigParam(CONF_MAX_PLAYLIST_LENGTH); - if(strcmp("yes",(getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS]) - ==0) { - playlist_saveAbsolutePaths = 1; - } - else if(strcmp("no",(getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS]) - ==0) { - playlist_saveAbsolutePaths = 0; + if(param) { + playlist_max_length = strtol(param->value, &test, 10); + if(*test!='\0') { + ERROR("max playlist length \"%s\" is not an integer, " + "line %i\n", param->value, param->line); + exit(EXIT_FAILURE); + } } - else { - ERROR("save_absolute_paths_in_playlist \"%s\" is not yes or " - "no\n", - (getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS]); - exit(EXIT_FAILURE); + + param = getConfigParam(CONF_SAVE_ABSOLUTE_PATHS); + + if(param) { + if(0 == strcmp("yes", param->value) ) { + playlist_saveAbsolutePaths = 1; + } + else if(0 == strcmp("no", param->value) ) { + playlist_saveAbsolutePaths = 0; + } + else { + ERROR("%s \"%s\" is not yes or no, line %i" + CONF_SAVE_ABSOLUTE_PATHS, + param->value, param->line); + exit(EXIT_FAILURE); + } } playlist.songs = malloc(sizeof(Song *)*playlist_max_length); @@ -169,9 +179,7 @@ void initPlaylist() { srand(time(NULL)); - if(getConf()[CONF_STATE_FILE]) { - playlist_stateFile = getConf()[CONF_STATE_FILE]; - } + playlist_stateFile = getConfigParamValue(CONF_STATE_FILE); for(i=0; i<playlist_max_length*PLAYLIST_HASH_MULT; i++) { playlist.idToPosition[i] = -1; diff --git a/src/replayGain.c b/src/replayGain.c index dbd09aa36..4788d7d95 100644 --- a/src/replayGain.c +++ b/src/replayGain.c @@ -32,34 +32,38 @@ static int replayGainState = REPLAYGAIN_OFF; static float replayGainPreamp = 1.0; void initReplayGainState() { - if(!getConf()[CONF_REPLAYGAIN]) return; + ConfigParam * param = getConfigParam(CONF_REPLAYGAIN); - if(strcmp(getConf()[CONF_REPLAYGAIN],"track")==0) { + if(!param) return; + + if(strcmp(param->value, "track") == 0) { replayGainState = REPLAYGAIN_TRACK; } - else if(strcmp(getConf()[CONF_REPLAYGAIN],"album")==0) { + else if(strcmp(param->value, "album") == 0) { replayGainState = REPLAYGAIN_ALBUM; } else { - ERROR("replaygain value \"%s\" is invalid\n", - getConf()[CONF_REPLAYGAIN]); + ERROR("replaygain value \"%s\" at line %i is invalid\n", + param->value, param->line); exit(EXIT_FAILURE); } - if(getConf()[CONF_REPLAYGAIN_PREAMP]) { + param = getConfigParam(CONF_REPLAYGAIN_PREAMP); + + if(param) { char * test; - float f = strtod(getConf()[CONF_REPLAYGAIN_PREAMP], &test); + float f = strtod(param->value, &test); if(*test != '\0') { - ERROR("Replaygain preamp \"%s\" is not a number\n", - getConf()[CONF_REPLAYGAIN_PREAMP]); + ERROR("Replaygain preamp \"%s\" is not a number at " + "line %i\n", param->value, param->line); exit(EXIT_FAILURE); } if(f < -15 || f > 15) { ERROR("Replaygain preamp \"%s\" is not between -15 and" - "15\n", - getConf()[CONF_REPLAYGAIN_PREAMP]); + "15 at line %i\n", + param->value, param->line); exit(EXIT_FAILURE); } @@ -93,18 +93,6 @@ char * getID3Info(struct id3_tag * tag, char * id) { utf8 = id3_ucs4_utf8duplicate(ucs4); if(!utf8) return NULL; - if(getConf()[CONF_ID3V1_ENCODING] - && (id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1)) { - - char* isostr; - setCharSetConversion("ISO-8859-1", "UTF-8"); - isostr = convStrDup(utf8); - free(utf8); - setCharSetConversion("UTF-8", getConf()[CONF_ID3V1_ENCODING]); - utf8 = convStrDup(isostr); - free(isostr); - } - return utf8; } #endif diff --git a/src/volume.c b/src/volume.c index fa2f8aaa9..cd48f76f4 100644 --- a/src/volume.c +++ b/src/volume.c @@ -45,8 +45,21 @@ #define VOLUME_MIXER_ALSA_DEFAULT "default" #define VOLUME_MIXER_ALSA_CONTROL_DEFAULT "Master" -int volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE; -char * volume_mixerDevice; +#ifndef NO_OSS_MIXER +#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_OSS +#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_OSS_DEFAULT +#else +#ifdef HAVE_ALSA +#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_ALSA +#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_ALSA_DEFAULT +#else +#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_SOFTWARE +#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_SOFTWARE_DEFAULT +#endif +#endif + +int volume_mixerType = VOLUME_MIXER_TYPE_DEFAULT; +char * volume_mixerDevice = VOLUME_MIXER_DEVICE_DEFAULT; int volume_softwareSet = 100; @@ -66,13 +79,16 @@ int volume_alsaSet = -1; #ifndef NO_OSS_MIXER int prepOssMixer(char * device) { int devmask = 0; + ConfigParam * param; if((volume_ossFd = open(device,O_RDONLY))<0) { WARNING("unable to open oss mixer \"%s\"\n",device); return -1; } - if(getConf()[CONF_MIXER_CONTROL]) { + param = getConfigParam(CONF_MIXER_CONTROL); + + if(param) { char * labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS; char * dup; int i,j; @@ -88,7 +104,7 @@ int prepOssMixer(char * device) { /* eliminate spaces at the end */ j = strlen(dup)-1; while(j>=0 && dup[j]==' ') dup[j--] = '\0'; - if(strcasecmp(dup,getConf()[CONF_MIXER_CONTROL])==0) { + if(strcasecmp(dup, param->value)==0) { free(dup); break; } @@ -96,14 +112,14 @@ int prepOssMixer(char * device) { } if(i>=SOUND_MIXER_NRDEVICES) { - WARNING("mixer control \"%s\" not found\n", - getConf()[CONF_MIXER_CONTROL]); + WARNING("mixer control \"%s\" not found at line %i\n", + param->value, param->line); close(volume_ossFd); return -1; } else if(!( ( 1 << i ) & devmask )) { - WARNING("mixer control \"%s\" not usable\n", - getConf()[CONF_MIXER_CONTROL]); + WARNING("mixer control \"%s\" not usable at line %i\n", + param->value, param->line); close(volume_ossFd); return -1; } @@ -173,6 +189,7 @@ int prepAlsaMixer(char * card) { int err; snd_mixer_elem_t * elem; char * controlName = VOLUME_MIXER_ALSA_CONTROL_DEFAULT; + ConfigParam * param; if((err = snd_mixer_open(&volume_alsaMixerHandle,0))<0) { WARNING("problems opening alsa mixer: %s\n",snd_strerror(err)); @@ -201,8 +218,11 @@ int prepAlsaMixer(char * card) { } elem = snd_mixer_first_elem(volume_alsaMixerHandle); - if(getConf()[CONF_MIXER_CONTROL]) { - controlName = getConf()[CONF_MIXER_CONTROL]; + + param = getConfigParam(CONF_MIXER_CONTROL); + + if(param) { + controlName = param->value; } while(elem) { @@ -340,29 +360,37 @@ void finishVolume() { } void initVolume() { - if(0); + ConfigParam * param = getConfigParam(CONF_MIXER_TYPE); + + if(param) { + if(0); #ifdef HAVE_ALSA - else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_ALSA)==0) { - volume_mixerType = VOLUME_MIXER_TYPE_ALSA; - volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT; - } + else if(strcmp(param->value, VOLUME_MIXER_ALSA)==0) { + volume_mixerType = VOLUME_MIXER_TYPE_ALSA; + volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT; + } #endif #ifndef NO_OSS_MIXER - else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_OSS)==0) { - volume_mixerType = VOLUME_MIXER_TYPE_OSS; - volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT; - } + else if(strcmp(param->value, VOLUME_MIXER_OSS)==0) { + volume_mixerType = VOLUME_MIXER_TYPE_OSS; + volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT; + } #endif - else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_SOFTWARE)==0) { - volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE; - volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT; - } - else { - ERROR("unknown mixer type: %s\n",(getConf())[CONF_MIXER_TYPE]); - exit(EXIT_FAILURE); + else if(strcmp(param->value ,VOLUME_MIXER_SOFTWARE)==0) { + volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE; + volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT; + } + else { + ERROR("unknown mixer type %s at line %i\n", + param->value, param->line); + exit(EXIT_FAILURE); + } } - if(strlen((getConf())[CONF_MIXER_DEVICE])) { - volume_mixerDevice = (getConf())[CONF_MIXER_DEVICE]; + + param = getConfigParam(CONF_MIXER_DEVICE); + + if(param) { + volume_mixerDevice = param->value; } } @@ -431,4 +459,3 @@ int changeVolumeLevel(FILE * fp, int change, int rel) { break; } } -/* vim:set shiftwidth=4 tabstop=8 expandtab: */ |