static int init(void) { const char *type; if(validateConfigString(&config, "volume.response.type", &type, -1) == EXIT_SUCCESS) { if(strcmp(type, "lower_limit")) modVolumeResponseCondResize.process = &processLower; else if(strcmp(type, "upper_limit")) modVolumeResponseCondResize.process = &processUpper; else return EXIT_FAILURE; } if(validateConfigInt(&config, "volume.response.limit", &responseLimit, -1, 0, 0, -1) == EXIT_FAILURE) return EXIT_FAILURE; if(validateConfigDouble(&config, "volume.response.divisor", &responseDivisor, -1, 0, 0, -1) == EXIT_FAILURE) return EXIT_FAILURE; #ifdef REDUNDANT // causes segfault, process not yet loaded if(strcasecmp(common_data.process->name, "numeric") && (int)responseDivisor != responseDivisor) { syslog(LOG_ERR, "[ERROR] Numeric does not 'float'! Setting 'volume.response.divisor'" " is not an integer: %.2f", responseDivisor); return EXIT_FAILURE; } #endif if(responseDivisor == 1) common_data.mod->volumeResponse = NULL; return EXIT_SUCCESS; }
/* Will validate the data retrieved from the configuration file */ int init(void) { int status; config_setting_t *conf_setting = NULL; const char *conf_value = NULL; /* Now the configuration file is read, we don't need to know the location * of the application anymore. We'll change working directory to root */ if(chdir("/") < 0) { syslog(LOG_ERR, "Unable to change working directory to root: %s", strerror(errno)); return EXIT_FAILURE; } syslog(LOG_INFO, "Checking presence and validity of required variables:"); validateConfigBool(&config, "sync_2way", &common_data.sync_2way, 0); validateConfigBool(&config, "diff_commands", &common_data.diff_commands, 0); common_data.send_query = config_lookup(&config, "query") ? 1:0; if(common_data.send_query && ((conf_setting = config_lookup(&config, "query.trigger")) == NULL || config_setting_is_array(conf_setting) == CONFIG_FALSE || (common_data.statusQueryLength = config_setting_length(conf_setting)) == 0)) { syslog(LOG_ERR, "[ERROR] Setting is not present or not formatted as array: query.trigger"); return EXIT_FAILURE; } if(common_data.send_query && validateConfigInt(&config, "query.interval", &common_data.statusQueryInterval, -1, 0, 255, -1) == EXIT_FAILURE) return EXIT_FAILURE; /* Set volume (curve) functions */ conf_value = NULL; config_lookup_string(&config, "volume.curve", &conf_value); if(!(common_data.volume = getVolume(&conf_value))) { syslog(LOG_ERR, "[Error] Volume curve is not recognised: %s", conf_value); return EXIT_FAILURE; } else { syslog(LOG_INFO, "[OK] volume.curve: %s", conf_value); } /* initialise volume variables */ if(common_data.volume->init() == EXIT_FAILURE) return EXIT_FAILURE; /* Set and initialise process type */ conf_value = NULL; config_lookup_string(&config, "data_type", &conf_value); if(!(common_data.process = getProcessMethod(&conf_value))) { syslog(LOG_ERR, "[Error] Setting 'data_type' is not recognised: %s", conf_value); return EXIT_FAILURE; } else { syslog(LOG_INFO, "[OK] data_type: %s", conf_value); } if(common_data.process->init() == EXIT_FAILURE) return EXIT_FAILURE; /* Set and initialise communication interface */ conf_value = NULL; config_lookup_string(&config, "interface", &conf_value); if(!(common_data.interface = getInterface(&conf_value))) { syslog(LOG_ERR, "[Error] Setting 'interface' is not recognised: %s", conf_value); return EXIT_FAILURE; } else { syslog(LOG_INFO, "[OK] interface: %s", conf_value); } if(common_data.interface->init() == EXIT_FAILURE) return EXIT_FAILURE; /* initialise mixer device */ if(initMixer() == EXIT_FAILURE) return EXIT_FAILURE; /* init multipliers */ common_data.volume->regenerateMultipliers(); #ifndef DISABLE_MSQ /* initialise message queue */ if(initMsQ() == EXIT_FAILURE) return EXIT_FAILURE; #endif if((status = pthread_mutex_init(&lockConfig, NULL)) != 0) { syslog(LOG_ERR, "Failed to create config mutex: %i", status); return EXIT_FAILURE; } return EXIT_SUCCESS; } /* end init */
static int init(void) { int count; int main_count; int int_setting = -1; char serial_command[200]; const char *char_setting = NULL; ascii_data.volumeMutationNegative = NULL; ascii_data.volumeMutationPositive = NULL; for(main_count = 0; main_count <= common_data.diff_commands; main_count++) { if(validateConfigString(&config, "header", &ascii_data.command_header[main_count], main_count) == EXIT_FAILURE) return EXIT_FAILURE; ascii_data.header_length[main_count] = strlen(ascii_data.command_header[main_count]); if(validateConfigString(&config, "tail", &ascii_data.command_tail[main_count], main_count) == EXIT_FAILURE) return EXIT_FAILURE; if(common_data.sync_2way && (ascii_data.tail_length[main_count] = strlen(ascii_data.command_tail[main_count])) < 1) { syslog(LOG_ERR, "[Error] Setting 'tail' can not be empty"); return EXIT_FAILURE; } if(validateConfigString(&config, "event_delimiter", &ascii_data.event_delimiter[main_count], main_count) == EXIT_FAILURE) return EXIT_FAILURE; ascii_data.event_delimiter_length[main_count] = strlen(ascii_data.event_delimiter[main_count]); if(validateConfigString(&config, "volume.header", &ascii_data.volume_header[main_count], main_count) == EXIT_FAILURE) return EXIT_FAILURE; if(validateConfigString(&config, "volume.tail", &ascii_data.volume_tail[main_count], main_count) == EXIT_FAILURE) return EXIT_FAILURE; } if(common_data.discrete_volume) { if(validateConfigInt(&config, "volume.precision", &ascii_data.volume_precision, -1, 0, 10, 0) == EXIT_FAILURE) return EXIT_FAILURE; if(validateConfigInt(&config, "volume.length", &ascii_data.volume_length, -1, 0, 10, 0) == EXIT_FAILURE) return EXIT_FAILURE; if(ascii_data.volume_precision) ascii_data.volume_length += ascii_data.volume_precision+1; } if(!common_data.discrete_volume) { if(validateConfigString(&config, "volume.min", &char_setting, -1) == EXIT_FAILURE) return EXIT_FAILURE; snprintf(serial_command, 200, "%s%s%s%s%s%s", ascii_data.command_header[0], ascii_data.volume_header[0], ascii_data.event_delimiter[0], char_setting, ascii_data.volume_tail[0], ascii_data.command_tail[0]); ascii_data.volumeMutationNegative = calloc(strlen(serial_command)+1, sizeof(char)); strcpy(ascii_data.volumeMutationNegative, serial_command); if(validateConfigString(&config, "volume.plus", &char_setting, -1) == EXIT_FAILURE) return EXIT_FAILURE; snprintf(serial_command, 200, "%s%s%s%s%s%s", ascii_data.command_header[0], ascii_data.volume_header[0], ascii_data.event_delimiter[0], char_setting, ascii_data.volume_tail[0], ascii_data.command_tail[0]); ascii_data.volumeMutationPositive = calloc(strlen(serial_command)+1, sizeof(char)); strcpy(ascii_data.volumeMutationPositive, serial_command); } if(common_data.volume_timeout) { if(smoothVolume.init(&sendSmoothVolumeCommand, (char *)ascii_data.volumeMutationNegative, (char *)ascii_data.volumeMutationPositive) == EXIT_FAILURE) return EXIT_FAILURE; } if(common_data.send_query && validateConfigString(&config, "query.trigger.[0]", &common_data.statusQuery, -1) == EXIT_FAILURE) return EXIT_FAILURE; if(common_data.send_query) common_data.statusQueryLength = strlen(common_data.statusQuery); if(config_lookup_string(&config, "response.indicator", &ascii_data.requestIndicator)) { ascii_data.allowRequests = 1; syslog(LOG_INFO, "[OK] response.indicator: %s", ascii_data.requestIndicator); } else ascii_data.allowRequests = 0; if(common_data.mod->command) { if(common_data.mod->command->init(0) == EXIT_FAILURE) return EXIT_FAILURE; } return EXIT_SUCCESS; } /* end init() */