diff options
Diffstat (limited to 'cras/src/server/cras_dsp_ini.c')
-rw-r--r-- | cras/src/server/cras_dsp_ini.c | 492 |
1 files changed, 0 insertions, 492 deletions
diff --git a/cras/src/server/cras_dsp_ini.c b/cras/src/server/cras_dsp_ini.c deleted file mode 100644 index a331acf8..00000000 --- a/cras/src/server/cras_dsp_ini.c +++ /dev/null @@ -1,492 +0,0 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <errno.h> -#include <stdlib.h> -#include <syslog.h> -#include "cras_dsp_ini.h" -#include "iniparser_wrapper.h" - -#define MAX_NR_PORT 128 /* the max number of ports for a plugin */ -#define MAX_PORT_NAME_LENGTH 20 /* names like "output_32" */ -#define MAX_MOCK_INI_CH 20 /* Max number of channels to create mock ini */ - -/* Format of the ini file (See dsp.ini.sample for an example). - -- Each section in the ini file specifies a plugin. The section name is - just an identifier. The "library" and "label" attributes in a - section must be defined. The "library" attribute is the name of the - shared library from which this plugin will be loaded, or a special - value "builtin" for built-in plugins. The "label" attribute specify - which plugin inside the shared library should be loaded. - -- Built-in plugins have an attribute "label" which has value "source" - or "sink". It defines where the audio data flows into and flows out - of the pipeline. Built-in plugins also have a attribute "purpose" - which has the value "playback" or "capture". It defines which - pipeline these plugins belong to. - -- Each plugin can have an optional "disable expression", which defines - under which conditions the plugin is disabled. - -- Each plugin have some ports which specify the parameters for the - plugin or to specify connections to other plugins. The ports in each - plugin are numbered from 0. Each port is either an input port or an - output port, and each port is either an audio port or a control - port. The connections between two ports are expressed by giving the - same value to both ports. For audio ports, the value should be - "{identifier}". For control ports, the value shoule be - "<identifier>". For example, the following fragment - - [plugin1] - ... - output_4={audio_left} - output_5={audio_right} - - [plugin2] - ... - input_0={audio_left} - - [plugin3] - ... - input_2={audio_right} - - specifies these connections: - port 4 of plugin1 --> port 0 of plugin2 - port 5 of plugin1 --> port 2 of plugin3 - -*/ - -static const char *getstring(struct ini *ini, const char *sec_name, - const char *key) -{ - char full_key[MAX_INI_KEY_LENGTH + 1]; - snprintf(full_key, sizeof(full_key), "%s:%s", sec_name, key); - return iniparser_getstring(ini->dict, full_key, NULL); -} - -static int lookup_flow(struct ini *ini, const char *name) -{ - int i; - const struct flow *flow; - - ARRAY_ELEMENT_FOREACH (&ini->flows, i, flow) { - if (strcmp(flow->name, name) == 0) - return i; - } - - return -1; -} - -static int lookup_or_add_flow(struct ini *ini, const char *name) -{ - struct flow *flow; - int i = lookup_flow(ini, name); - if (i != -1) - return i; - i = ARRAY_COUNT(&ini->flows); - flow = ARRAY_APPEND_ZERO(&ini->flows); - flow->name = name; - return i; -} - -static int parse_ports(struct ini *ini, const char *sec_name, - struct plugin *plugin) -{ - char key[MAX_PORT_NAME_LENGTH]; - const char *str; - int i; - struct port *p; - int direction; - - for (i = 0; i < MAX_NR_PORT; i++) { - direction = PORT_INPUT; - snprintf(key, sizeof(key), "input_%d", i); - str = getstring(ini, sec_name, key); - if (str == NULL) { - direction = PORT_OUTPUT; - snprintf(key, sizeof(key), "output_%d", i); - str = getstring(ini, sec_name, key); - if (str == NULL) - break; /* no more ports */ - } - - if (*str == '\0') { - syslog(LOG_ERR, "empty value for %s:%s", sec_name, key); - return -1; - } - - if (str[0] == '<' || str[0] == '{') { - p = ARRAY_APPEND_ZERO(&plugin->ports); - p->type = (str[0] == '<') ? PORT_CONTROL : PORT_AUDIO; - p->flow_id = lookup_or_add_flow(ini, str); - p->init_value = 0; - } else { - char *endptr; - float init_value = strtof(str, &endptr); - if (endptr == str) { - syslog(LOG_ERR, "cannot parse number from '%s'", - str); - } - p = ARRAY_APPEND_ZERO(&plugin->ports); - p->type = PORT_CONTROL; - p->flow_id = INVALID_FLOW_ID; - p->init_value = init_value; - } - p->direction = direction; - } - - return 0; -} - -static int parse_plugin_section(struct ini *ini, const char *sec_name, - struct plugin *p) -{ - p->title = sec_name; - p->library = getstring(ini, sec_name, "library"); - p->label = getstring(ini, sec_name, "label"); - p->purpose = getstring(ini, sec_name, "purpose"); - p->disable_expr = - cras_expr_expression_parse(getstring(ini, sec_name, "disable")); - - if (p->library == NULL || p->label == NULL) { - syslog(LOG_ERR, "A plugin must have library and label: %s", - sec_name); - return -1; - } - - if (parse_ports(ini, sec_name, p) < 0) { - syslog(LOG_ERR, "Failed to parse ports: %s", sec_name); - return -1; - } - - return 0; -} - -static void fill_flow_info(struct ini *ini) -{ - int i, j; - struct plugin *plugin; - struct port *port; - struct flow *flow; - struct plugin **pplugin; - int *pport; - - ARRAY_ELEMENT_FOREACH (&ini->plugins, i, plugin) { - ARRAY_ELEMENT_FOREACH (&plugin->ports, j, port) { - int flow_id = port->flow_id; - if (flow_id == INVALID_FLOW_ID) - continue; - flow = ARRAY_ELEMENT(&ini->flows, flow_id); - flow->type = port->type; - if (port->direction == PORT_INPUT) { - pplugin = &flow->to; - pport = &flow->to_port; - } else { - pplugin = &flow->from; - pport = &flow->from_port; - } - *pplugin = plugin; - *pport = j; - } - } -} - -/* Adds a port to a plugin with specified flow id and direction. */ -static void add_audio_port(struct ini *ini, struct plugin *plugin, int flow_id, - enum port_direction port_direction) -{ - struct port *p; - p = ARRAY_APPEND_ZERO(&plugin->ports); - p->type = PORT_AUDIO; - p->flow_id = flow_id; - p->init_value = 0; - p->direction = port_direction; -} - -/* Fills fields for a swap_lr plugin.*/ -static void fill_swap_lr_plugin(struct ini *ini, struct plugin *plugin, - int input_flowid_0, int input_flowid_1, - int output_flowid_0, int output_flowid_1) -{ - plugin->title = "swap_lr"; - plugin->library = "builtin"; - plugin->label = "swap_lr"; - plugin->purpose = "playback"; - plugin->disable_expr = cras_expr_expression_parse("swap_lr_disabled"); - - add_audio_port(ini, plugin, input_flowid_0, PORT_INPUT); - add_audio_port(ini, plugin, input_flowid_1, PORT_INPUT); - add_audio_port(ini, plugin, output_flowid_0, PORT_OUTPUT); - add_audio_port(ini, plugin, output_flowid_1, PORT_OUTPUT); -} - -/* Adds a new flow with name. If there is already a flow with the name, returns - * INVALID_FLOW_ID. - */ -static int add_new_flow(struct ini *ini, const char *name) -{ - struct flow *flow; - int i = lookup_flow(ini, name); - if (i != -1) - return INVALID_FLOW_ID; - i = ARRAY_COUNT(&ini->flows); - flow = ARRAY_APPEND_ZERO(&ini->flows); - flow->name = name; - return i; -} - -/* Finds the first playback sink plugin in ini. */ -struct plugin *find_first_playback_sink_plugin(struct ini *ini) -{ - int i; - struct plugin *plugin; - - ARRAY_ELEMENT_FOREACH (&ini->plugins, i, plugin) { - if (strcmp(plugin->library, "builtin") != 0) - continue; - if (strcmp(plugin->label, "sink") != 0) - continue; - if (!plugin->purpose || - strcmp(plugin->purpose, "playback") != 0) - continue; - return plugin; - } - - return NULL; -} - -/* Inserts a swap_lr plugin before sink. Handles the port change such that - * the port originally connects to sink will connect to swap_lr. - */ -static int insert_swap_lr_plugin(struct ini *ini) -{ - struct plugin *swap_lr, *sink; - int sink_input_flowid_0, sink_input_flowid_1; - int swap_lr_output_flowid_0, swap_lr_output_flowid_1; - - /* Only add swap_lr plugin for two-channel playback dsp. - * TODO(cychiang): Handle multiple sinks if needed. - */ - sink = find_first_playback_sink_plugin(ini); - if ((sink == NULL) || ARRAY_COUNT(&sink->ports) != 2) - return 0; - - /* Gets the original flow ids of the sink input ports. */ - sink_input_flowid_0 = ARRAY_ELEMENT(&sink->ports, 0)->flow_id; - sink_input_flowid_1 = ARRAY_ELEMENT(&sink->ports, 1)->flow_id; - - /* Create new flow ids for swap_lr output ports. */ - swap_lr_output_flowid_0 = add_new_flow(ini, "{swap_lr_out:0}"); - swap_lr_output_flowid_1 = add_new_flow(ini, "{swap_lr_out:1}"); - - if (swap_lr_output_flowid_0 == INVALID_FLOW_ID || - swap_lr_output_flowid_1 == INVALID_FLOW_ID) { - syslog(LOG_ERR, "Can not create flow id for swap_lr_out"); - return -EINVAL; - } - - /* Creates a swap_lr plugin and sets the input and output ports. */ - swap_lr = ARRAY_APPEND_ZERO(&ini->plugins); - fill_swap_lr_plugin(ini, swap_lr, sink_input_flowid_0, - sink_input_flowid_1, swap_lr_output_flowid_0, - swap_lr_output_flowid_1); - - /* Look up first sink again because ini->plugins could be realloc'ed */ - sink = find_first_playback_sink_plugin(ini); - - /* The flow ids of sink input ports should be changed to flow ids of - * {swap_lr_out:0}, {swap_lr_out:1}. */ - ARRAY_ELEMENT(&sink->ports, 0)->flow_id = swap_lr_output_flowid_0; - ARRAY_ELEMENT(&sink->ports, 1)->flow_id = swap_lr_output_flowid_1; - - return 0; -} - -struct ini *create_mock_ini(const char *purpose, unsigned int num_channels) -{ - static char mock_flow_names[MAX_MOCK_INI_CH][9] = { - "{tmp:0}", "{tmp:1}", "{tmp:2}", "{tmp:3}", "{tmp:4}", - "{tmp:5}", "{tmp:6}", "{tmp:7}", "{tmp:8}", "{tmp:9}", - "{tmp:10}", "{tmp:11}", "{tmp:12}", "{tmp:13}", "{tmp:14}", - "{tmp:15}", "{tmp:16}", "{tmp:17}", "{tmp:18}", "{tmp:19}", - }; - struct ini *ini; - struct plugin *source, *sink; - int tmp_flow_ids[MAX_MOCK_INI_CH]; - int i; - - if (num_channels > MAX_MOCK_INI_CH) { - syslog(LOG_ERR, "Unable to create %u channels of mock ini", - num_channels); - return NULL; - } - - ini = calloc(1, sizeof(struct ini)); - if (!ini) { - syslog(LOG_ERR, "no memory for ini struct"); - return NULL; - } - - for (i = 0; i < num_channels; i++) - tmp_flow_ids[i] = add_new_flow(ini, mock_flow_names[i]); - - source = ARRAY_APPEND_ZERO(&ini->plugins); - source->title = "source"; - source->library = "builtin"; - source->label = "source"; - source->purpose = purpose; - - for (i = 0; i < num_channels; i++) - add_audio_port(ini, source, tmp_flow_ids[i], PORT_OUTPUT); - - sink = ARRAY_APPEND_ZERO(&ini->plugins); - sink->title = "sink"; - sink->library = "builtin"; - sink->label = "sink"; - sink->purpose = purpose; - - for (i = 0; i < num_channels; i++) - add_audio_port(ini, sink, tmp_flow_ids[i], PORT_INPUT); - - fill_flow_info(ini); - - return ini; -} - -struct ini *cras_dsp_ini_create(const char *ini_filename) -{ - struct ini *ini; - dictionary *dict; - int nsec, i; - const char *sec_name; - struct plugin *plugin; - int rc; - - ini = calloc(1, sizeof(struct ini)); - if (!ini) { - syslog(LOG_ERR, "no memory for ini struct"); - return NULL; - } - - dict = iniparser_load_wrapper((char *)ini_filename); - if (!dict) { - syslog(LOG_DEBUG, "no ini file %s", ini_filename); - goto bail; - } - ini->dict = dict; - - /* Parse the plugin sections */ - nsec = iniparser_getnsec(dict); - for (i = 0; i < nsec; i++) { - sec_name = iniparser_getsecname(dict, i); - plugin = ARRAY_APPEND_ZERO(&ini->plugins); - if (parse_plugin_section(ini, sec_name, plugin) < 0) - goto bail; - } - - /* Insert a swap_lr plugin before sink. */ - rc = insert_swap_lr_plugin(ini); - if (rc < 0) { - syslog(LOG_ERR, "failed to insert swap_lr plugin"); - goto bail; - } - - /* Fill flow info now because now the plugin array won't change */ - fill_flow_info(ini); - - return ini; -bail: - cras_dsp_ini_free(ini); - return NULL; -} - -void cras_dsp_ini_free(struct ini *ini) -{ - struct plugin *p; - int i; - - /* free plugins */ - ARRAY_ELEMENT_FOREACH (&ini->plugins, i, p) { - cras_expr_expression_free(p->disable_expr); - ARRAY_FREE(&p->ports); - } - ARRAY_FREE(&ini->plugins); - ARRAY_FREE(&ini->flows); - - if (ini->dict) { - iniparser_freedict(ini->dict); - ini->dict = NULL; - } - - free(ini); -} - -static const char *port_direction_str(enum port_direction port_direction) -{ - switch (port_direction) { - case PORT_INPUT: - return "input"; - case PORT_OUTPUT: - return "output"; - default: - return "unknown"; - } -} - -static const char *port_type_str(enum port_type port_type) -{ - switch (port_type) { - case PORT_CONTROL: - return "control"; - case PORT_AUDIO: - return "audio"; - default: - return "unknown"; - } -} - -static const char *plugin_title(struct plugin *plugin) -{ - if (plugin == NULL) - return "(null)"; - return plugin->title; -} - -void cras_dsp_ini_dump(struct dumper *d, struct ini *ini) -{ - int i, j; - struct plugin *plugin; - struct port *port; - const struct flow *flow; - - dumpf(d, "---- ini dump begin ---\n"); - dumpf(d, "ini->dict = %p\n", ini->dict); - - dumpf(d, "number of plugins = %d\n", ARRAY_COUNT(&ini->plugins)); - ARRAY_ELEMENT_FOREACH (&ini->plugins, i, plugin) { - dumpf(d, "[plugin %d: %s]\n", i, plugin->title); - dumpf(d, "library=%s\n", plugin->library); - dumpf(d, "label=%s\n", plugin->label); - dumpf(d, "purpose=%s\n", plugin->purpose); - dumpf(d, "disable=%p\n", plugin->disable_expr); - ARRAY_ELEMENT_FOREACH (&plugin->ports, j, port) { - dumpf(d, - " [%s port %d] type=%s, flow_id=%d, value=%g\n", - port_direction_str(port->direction), j, - port_type_str(port->type), port->flow_id, - port->init_value); - } - } - - dumpf(d, "number of flows = %d\n", ARRAY_COUNT(&ini->flows)); - ARRAY_ELEMENT_FOREACH (&ini->flows, i, flow) { - dumpf(d, " [flow %d] %s, %s, %s:%d -> %s:%d\n", i, flow->name, - port_type_str(flow->type), plugin_title(flow->from), - flow->from_port, plugin_title(flow->to), flow->to_port); - } - - dumpf(d, "---- ini dump end ----\n"); -} |