예제 #1
0
/**
 * Parse the "routes" section, a string on the form
 *  a>b, c>d, e>f, ...
 * where a... are non-unique, non-negative integers
 * and input channel a gets copied to output channel b, etc.
 * @param param the configuration block to read
 * @param filter a route_filter whose min_channels and sources[] to set
 * @return true on success, false on error
 */
static bool
route_filter_parse(const struct config_param *param,
		   struct route_filter *filter,
		   GError **error_r) {

	/* TODO:
	 * With a more clever way of marking "don't copy to output N",
	 * This could easily be merged into a single loop with some
	 * dynamic g_realloc() instead of one count run and one g_malloc().
	 */

	gchar **tokens;
	int number_of_copies;

	// A cowardly default, just passthrough stereo
	const char *routes =
		config_get_block_string(param, "routes", "0>0, 1>1");

	filter->min_input_channels = 0;
	filter->min_output_channels = 0;

	tokens = g_strsplit(routes, ",", 255);
	number_of_copies = g_strv_length(tokens);

	// Start by figuring out a few basic things about the routing set
	for (int c=0; c<number_of_copies; ++c) {

		// String and int representations of the source/destination
		gchar **sd;
		int source, dest;

		// Squeeze whitespace
		g_strstrip(tokens[c]);

		// Split the a>b string into source and destination
		sd = g_strsplit(tokens[c], ">", 2);
		if (g_strv_length(sd) != 2) {
			g_set_error(error_r, config_quark(), 1,
				"Invalid copy around %d in routes spec: %s",
				param->line, tokens[c]);
			g_strfreev(sd);
			g_strfreev(tokens);
			return false;
		}

		source = strtol(sd[0], NULL, 10);
		dest = strtol(sd[1], NULL, 10);

		// Keep track of the highest channel numbers seen
		// as either in- or outputs
		if (source >= filter->min_input_channels)
			filter->min_input_channels = source + 1;
		if (dest   >= filter->min_output_channels)
			filter->min_output_channels = dest + 1;

		g_strfreev(sd);
	}

	if (!audio_valid_channel_count(filter->min_output_channels)) {
		g_strfreev(tokens);
		g_set_error(error_r, audio_format_quark(), 0,
			    "Invalid number of output channels requested: %d",
			    filter->min_output_channels);
		return false;
	}

	// Allocate a map of "copy nothing to me"
	filter->sources =
		g_malloc(filter->min_output_channels * sizeof(signed char));

	for (int i=0; i<filter->min_output_channels; ++i)
		filter->sources[i] = -1;

	// Run through the spec again, and save the
	// actual mapping output <- input
	for (int c=0; c<number_of_copies; ++c) {

		// String and int representations of the source/destination
		gchar **sd;
		int source, dest;

		// Split the a>b string into source and destination
		sd = g_strsplit(tokens[c], ">", 2);
		if (g_strv_length(sd) != 2) {
			g_set_error(error_r, config_quark(), 1,
				"Invalid copy around %d in routes spec: %s",
				param->line, tokens[c]);
			g_strfreev(sd);
			g_strfreev(tokens);
			return false;
		}

		source = strtol(sd[0], NULL, 10);
		dest = strtol(sd[1], NULL, 10);

		filter->sources[dest] = source;

		g_strfreev(sd);
	}

	g_strfreev(tokens);

	return true;
}
예제 #2
0
config_t* load_config(GError** err){
    
    GKeyFile *k = g_key_file_new();
    
    // load config file
    gchar* config_file = g_build_filename(g_get_home_dir(), ".podcastrc", NULL);
    if(!g_key_file_load_from_file(k, config_file, G_KEY_FILE_NONE, err)){
        g_free(config_file);
        return NULL;
    }
    g_free(config_file);
    
    // initialize config structures
    config_t* config = (config_t*) malloc(sizeof(config_t));
    if(config == NULL){
        g_set_error(err, config_quark(), CONFIG_ERR_MEMORY_ALLOC,
            "malloc: Failed to alloc memory for read the config_t* structure.\n");
        return NULL;
    }
    config->main_config = (main_config_t*) malloc(sizeof(main_config_t));
    if(config->main_config == NULL){
        g_set_error(err, config_quark(), CONFIG_ERR_MEMORY_ALLOC,
            "malloc: Failed to alloc memory for read the main_config_t* structure.\n");
        return NULL;
    }
    
    // storage variables
    gsize num_keys;
    gchar **keys;
    gchar *tmp = NULL;
    
    // load main config parameters
    if(!g_key_file_has_group(k, "main")){
        g_set_error(err, config_quark(), CONFIG_ERR_NO_MAIN,
            "g_key_file_has_group: Your configuration file should have a [main] section.\n");
        return NULL;
    }
    keys = g_key_file_get_keys(k, "main", &num_keys, err);
    for(int i=0; i<num_keys; i++){
        tmp = g_key_file_get_value(k, "main", keys[i], err);
        if(*err != NULL){
            return NULL;
        }
        if(g_strcmp0(keys[i], "download_command") == 0){
            config->main_config->download_command = g_strdup(tmp);
            g_free(tmp);
        }
        else if(g_strcmp0(keys[i], "player_command") == 0){
            config->main_config->player_command = g_strdup(tmp);
            g_free(tmp);
        }
        else if(g_strcmp0(keys[i], "media_directory") == 0){
            config->main_config->media_directory = g_strdup(tmp);
            g_free(tmp);
        }
        else{
            g_set_error(err, config_quark(), CONFIG_INVALID_PARAM,
                "Invalid configuration parameter: %s.\n", keys[i]);
            g_free(tmp);
            return NULL;
        }
    }
    g_strfreev(keys);
    
    // load feed urls
    if(!g_key_file_has_group(k, "podcast")){
        g_set_error(err, config_quark(), CONFIG_ERR_NO_PODCAST,
            "g_key_file_has_group: Your configuration file should have a [podcast] section.\n");
        return NULL;
    }
    config->podcasts = NULL;
    keys = g_key_file_get_keys(k, "podcast", &num_keys, err);
    for(config->pod_len = 0; config->pod_len < num_keys; config->pod_len++){
        tmp = g_key_file_get_value(k, "podcast", keys[config->pod_len], err);
        if(*err != NULL){
            return NULL;
        }
        config->podcasts = (podcast_t**) realloc(
            config->podcasts, (config->pod_len + 1) * sizeof(podcast_t*)
        );
        if(config->podcasts == NULL){
            g_set_error(err, config_quark(), CONFIG_ERR_MEMORY_ALLOC,
                "malloc: Failed to alloc memory for read the podcast_t** structure.\n");
            return NULL;
        }
        config->podcasts[config->pod_len] = (podcast_t*) malloc(sizeof(podcast_t));
        if(config->podcasts[config->pod_len] == NULL){
            g_set_error(err, config_quark(), CONFIG_ERR_MEMORY_ALLOC,
                "malloc: Failed to alloc memory for read the podcast_t* structure.\n");
            return NULL;
        }
        config->podcasts[config->pod_len]->id = g_strdup(keys[config->pod_len]);
        config->podcasts[config->pod_len]->feed_url = g_strdup(tmp);
        g_free(tmp);
    }
    g_strfreev(keys);
        
    g_key_file_free(k);
    return config;
}