sintonia/library/ecasound-2.7.2/libecasound/eca-control.cpp

1524 lines
49 KiB
C++

// ------------------------------------------------------------------------
// eca-control.cpp: Class for controlling the whole ecasound library
// Copyright (C) 1999-2005,2008,2009 Kai Vehmanen
// Copyright (C) 2005 Stuart Allie
// Copyright (C) 2009 Adam Linson
//
// Attributes:
// eca-style-version: 3 (see Ecasound Programmer's Guide)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <cassert>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <unistd.h>
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#include <kvu_utils.h> /* string_to_vector(), string_to_int_vector() */
#include <kvu_value_queue.h>
#include <kvu_message_item.h>
#include <kvu_dbc.h>
#include <kvu_numtostr.h>
#include "audioio.h"
#include "eca-chain.h"
#include "eca-chainop.h"
#include "eca-chainsetup.h"
#include "eca-control.h"
#include "eca-control-main.h"
#include "eca-engine.h"
#include "eca-object-factory.h"
#include "eca-object-map.h"
#include "eca-preset-map.h"
#include "eca-session.h"
#include "generic-controller.h"
#include "eca-chainop.h"
#include "audiofx_ladspa.h"
#include "preset.h"
#include "sample-specs.h"
#include "jack-connections.h"
#include "eca-version.h"
#include "eca-error.h"
#include "eca-logger.h"
#include "eca-logger-wellformed.h"
/**
* Import namespaces
*/
using std::string;
using std::list;
using std::vector;
using std::cerr;
using std::endl;
using namespace ECA;
/**
* Declarations for private static functions
*/
static string eca_aio_register_sub(ECA_OBJECT_MAP& objmap);
/**
* Definitions for member functions
*/
ECA_CONTROL::ECA_CONTROL (ECA_SESSION* psession)
: ctrl_dump_rep(this),
wellformed_mode_rep(false)
{
ECA_LOG_MSG(ECA_LOGGER::system_objects, "ECA_CONTROL constructor");
session_repp = psession;
selected_chainsetup_repp = psession->selected_chainsetup_repp;
engine_repp = 0;
engine_pid_rep = -1;
engine_exited_rep.set(0);
float_to_string_precision_rep = 3;
joining_rep = false;
DBC_CHECK(is_engine_created() != true);
selected_audio_object_repp = 0;
selected_audio_input_repp = 0;
selected_audio_output_repp = 0;
}
ECA_CONTROL::~ECA_CONTROL(void)
{
ECA_LOG_MSG(ECA_LOGGER::system_objects, "ECA_CONTROL destructor");
close_engine();
}
void ECA_CONTROL::fill_command_retval(struct eci_return_value *retval) const
{
if (retval == 0)
return;
*retval = last_retval_rep;
}
void ECA_CONTROL::command(const string& cmd_and_args, struct eci_return_value *retval)
{
clear_last_values();
clear_action_arguments();
ECA_LOG_MSG(ECA_LOGGER::user_objects, "processing cmd and arg: " + cmd_and_args);
vector<string> tokens = kvu_string_to_tokens_quoted(cmd_and_args);
vector<string>::iterator cmd = tokens.begin();
if (cmd != tokens.end()) {
const std::map<std::string,int>& cmdmap = ECA_IAMODE_PARSER::registered_commands();
if (cmdmap.find(*cmd) == cmdmap.end()) {
// ---
// *p is not recognized as a iamode command
// ---
if (cmd->size() > 0 && (*cmd)[0] == '-') {
// std::cerr << "Note! Direct use of EOS-options (-prefix:arg1,...,argN)" << " as iactive-mode commands is considered deprecated. " << "\tUse the notation 'cs-option -prefix:a,b,x' instead." << std::endl;
if (*cmd == "-i")
ECA_LOG_MSG(ECA_LOGGER::info,
"WARNING: syntax variant '-i file.ext' not supported, please use 'ai-add file.ext' instead.");
else if (*cmd == "-o")
ECA_LOG_MSG(ECA_LOGGER::info,
"WARNING: syntax variant '-o file.ext' not supported, please use 'ai-add file.ext' instead.");
else {
ECA_LOG_MSG(ECA_LOGGER::user_objects, "passiong to cs-option: " + cmd_and_args);
chainsetup_option(cmd_and_args);
}
}
else {
set_last_error("Unknown command!");
}
}
else {
int action_id = ECA_IAMODE_PARSER::command_to_action_id(*cmd);
if (action_id == ec_help) {
show_controller_help();
}
else {
vector<string>::iterator args = cmd + 1;
if (args != tokens.end()) {
set_action_argument(vector<string> (args, tokens.end()));
}
action(action_id);
}
}
}
fill_command_retval(retval);
}
void ECA_CONTROL::set_action_argument(const string& s)
{
action_args_rep.resize(0);
action_args_rep.push_back(s);
action_arg_f_set_rep = false;
}
void ECA_CONTROL::set_action_argument(const std::vector<std::string>& s)
{
action_args_rep = s;
action_arg_f_set_rep = false;
}
void ECA_CONTROL::set_action_argument(double v)
{
action_arg_f_rep = v;
action_arg_f_set_rep = true;
}
void ECA_CONTROL::clear_action_arguments(void)
{
// use resize() instead of clear(); clear() was a late
// addition to C++ standard and not supported by all
// compilers (for example egcs-2.91.66)
action_args_rep.resize(0);
action_arg_f_rep = 0.0f;
action_arg_f_set_rep = false;
}
double ECA_CONTROL::first_action_argument_as_float(void) const
{
if (action_arg_f_set_rep == true)
return action_arg_f_rep;
if (action_args_rep.size() == 0)
return 0.0f;
return atof(action_args_rep[0].c_str());
}
string ECA_CONTROL::first_action_argument_as_string(void) const
{
if (action_args_rep.size() == 0)
return std::string();
return action_args_rep[0];
}
const vector<string>& ECA_CONTROL::action_arguments_as_vector(void) const
{
return action_args_rep;
}
int ECA_CONTROL::first_action_argument_as_int(void) const
{
if (action_args_rep.size() == 0)
return 0;
return atoi(action_args_rep[0].c_str());
}
long int ECA_CONTROL::first_action_argument_as_long_int(void) const
{
if (action_args_rep.size() == 0)
return 0;
return atol(action_args_rep[0].c_str());
}
SAMPLE_SPECS::sample_pos_t ECA_CONTROL::first_action_argument_as_samples(void) const
{
if (action_args_rep.size() == 0)
return 0;
#ifdef HAVE_ATOLL
return atoll(action_args_rep[0].c_str());
#else
return atol(action_args_rep[0].c_str());
#endif
}
void ECA_CONTROL::command_float_arg(const string& cmd, double arg, struct eci_return_value *retval)
{
clear_action_arguments();
set_action_argument(arg);
int action_id = ec_unknown;
action_id = ECA_IAMODE_PARSER::command_to_action_id(cmd);
action(action_id);
fill_command_retval(retval);
}
/**
* Interprets an EOS (ecasound optiont syntax) token (prefixed with '-').
*/
void ECA_CONTROL::chainsetup_option(const string& cmd)
{
string prefix = kvu_get_argument_prefix(cmd);
if (prefix == "el" || prefix == "pn") { // --- LADSPA plugins and presets
if (selected_chains().size() == 1)
add_chain_operator(cmd);
else
set_last_error("When adding chain operators, only one chain can be selected.");
}
else if (ECA_OBJECT_FACTORY::chain_operator_map().object(prefix) != 0) {
if (selected_chains().size() == 1)
add_chain_operator(cmd);
else
set_last_error("When adding chain operators, only one chain can be selected.");
}
else if (ECA_OBJECT_FACTORY::controller_map().object(prefix) != 0) {
if (selected_chains().size() == 1)
add_controller(cmd);
else
set_last_error("When adding controllers, only one chain can be selected.");
}
else {
set_action_argument(cmd);
action(ec_cs_option);
}
}
/**
* Checks action preconditions.
*
* @return Sets status of private data members 'action_ok',
* 'action_restart', and 'action_reconnect'.
*/
void ECA_CONTROL::check_action_preconditions(int action_id)
{
action_ok = true;
action_reconnect = false;
action_restart = false;
/* case 1: action requiring arguments, but not arguments available */
if (action_arg_f_set_rep == false &&
first_action_argument_as_string().size() == 0 &&
action_requires_params(action_id)) {
set_last_error("Can't perform requested action; argument omitted.");
action_ok = false;
}
/* case 2: action requires an audio input, but no input available */
else if (is_selected() == true &&
get_audio_input() == 0 &&
action_requires_selected_audio_input(action_id)) {
set_last_error("Can't perform requested action; no audio input selected.");
action_ok = false;
}
/* case 3: action requires an audio output, but no output available */
else if (is_selected() == true &&
get_audio_output() == 0 &&
action_requires_selected_audio_output(action_id)) {
set_last_error("Can't perform requested action; no audio output selected.");
action_ok = false;
}
/* case 4: action requires a select chainsetup, but none selected */
else if (is_selected() == false &&
action_requires_selected(action_id)) {
if (!is_connected()) {
set_last_error("Can't perform requested action; no chainsetup selected.");
action_ok = false;
}
else {
ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: No chainsetup selected. Connected chainsetup will be selected.");
select_chainsetup(connected_chainsetup());
}
}
/* case 5: action requires a connected chainsetup, but none connected */
else if (is_connected() == false &&
action_requires_connected(action_id)) {
if (!is_selected()) {
set_last_error("Can't perform requested action; no chainsetup connected.");
action_ok = false;
}
else {
if (is_valid() == true) {
ECA_LOG_MSG(ECA_LOGGER::info,
"NOTE: No chainsetup connected. Trying to connect currently selected chainsetup \""
+ selected_chainsetup_repp->name()
+ "\"");
connect_chainsetup(0);
}
if (is_connected() != true) {
/* connect_chainsetup() sets last_error() so we just add to it */
set_last_error(last_error() + " Selected chainsetup cannot be connected. Can't perform requested action. ");
action_ok = false;
}
}
}
/* case 6: action can't be performed on a connected setup,
* but selected chainsetup is also connected */
else if (selected_chainsetup() == connected_chainsetup() &&
action_requires_selected_not_connected(action_id)) {
ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: This operation requires that chainsetup is disconnected. Temporarily disconnecting...");
if (is_running()) action_restart = true;
disconnect_chainsetup();
action_reconnect = true;
}
}
void ECA_CONTROL::action(int action_id,
const vector<string>& args)
{
ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: ECA_CONTROL::action() method is obsolete.\n");
clear_action_arguments();
set_action_argument(kvu_vector_to_string(args, " "));
action(action_id);
}
bool ECA_CONTROL::action_helper_check_cop_op_args(int copid, int coppid)
{
DBC_REQUIRE(is_selected() == true);
const vector<string>& selchains =
selected_chainsetup_repp->selected_chains();
bool res = false;
if (selchains.size() == 0) {
set_last_error("No chain selected, unable to identify chainop");
}
else if (selchains.size() > 1) {
set_last_error("More than one chain selected, unable to identify chainop");
}
else {
const CHAIN* selch =
selected_chainsetup_repp->get_chain_with_name(selchains[0]);
if (copid < 1 || copid > selch->number_of_chain_operators()) {
set_last_error("Invalid chainop-id, unable to identify chainop");
}
else if (coppid < 1) {
set_last_error("Invalid copp-id, indexing starts from 1.");
}
else {
res = true;
}
}
return res;
}
void ECA_CONTROL::action(int action_id)
{
clear_last_values();
check_action_preconditions(action_id);
if (action_ok != true) return;
switch(action_id) {
case ec_unknown: { set_last_error("Unknown command!"); break; }
// ---
// General
// ---
case ec_exit: { quit(); break; }
case ec_start:
{
if (is_running() != true) {
int result = start();
if (result < 0) {
set_last_error("Error, unable to start processing");
}
}
// ECA_LOG_MSG(ECA_LOGGER::info, "Can't perform requested action; no chainsetup connected.");
break;
}
case ec_stop: { if (is_running() == true) stop(); break; }
case ec_run:
{
int result = run();
if (result < 0) {
set_last_error("Errors during processing");
}
break;
}
case ec_debug:
{
int level = first_action_argument_as_int();
ECA_LOGGER::instance().set_log_level_bitmask(level);
set_last_string("Debug level set to " + kvu_numtostr(level) + ".");
break;
}
case ec_resource_file:
{
session_repp->interpret_general_option(string("-R:") +
first_action_argument_as_string());
break;
}
// ---
// Chainsetups
// ---
case ec_cs_add:
{
add_chainsetup(first_action_argument_as_string());
break;
}
case ec_cs_remove: { remove_chainsetup(); break; }
case ec_cs_list: { set_last_string_list(chainsetup_names()); break; }
case ec_cs_select: { select_chainsetup(first_action_argument_as_string()); break; }
case ec_cs_selected: { set_last_string(selected_chainsetup()); break; }
case ec_cs_index_select: {
if (first_action_argument_as_string().size() > 0) {
select_chainsetup_by_index(first_action_argument_as_int());
}
break;
}
case ec_cs_edit: { edit_chainsetup(); break; }
case ec_cs_load: { load_chainsetup(first_action_argument_as_string()); break; }
case ec_cs_save: { save_chainsetup(""); break; }
case ec_cs_save_as: { save_chainsetup(first_action_argument_as_string()); break; }
case ec_cs_is_valid: {
if (is_valid() == true)
set_last_integer(1);
else
set_last_integer(0);
break;
}
case ec_cs_connect:
{
if (is_valid() != false) {
connect_chainsetup(0);
}
else {
set_last_error("Can't connect; chainsetup not valid!");
}
break;
}
case ec_cs_connected: { set_last_string(connected_chainsetup()); break; }
case ec_cs_disconnect: { disconnect_chainsetup(); break; }
case ec_cs_set_param: { set_chainsetup_parameter(first_action_argument_as_string()); break; }
case ec_cs_set_audio_format: { set_chainsetup_sample_format(first_action_argument_as_string()); break; }
case ec_cs_status: {
set_last_string(chainsetup_status());
break;
}
case ec_cs_rewind: { change_chainsetup_position(-first_action_argument_as_float()); break; }
case ec_cs_forward: { change_chainsetup_position(first_action_argument_as_float()); break; }
case ec_cs_set_position: { set_chainsetup_position(first_action_argument_as_float()); break; }
case ec_cs_set_position_samples: { set_chainsetup_position_samples(first_action_argument_as_samples()); break; }
case ec_cs_get_position: { set_last_float(position_in_seconds_exact()); break; }
case ec_cs_get_position_samples: { set_last_long_integer(selected_chainsetup_repp->position_in_samples()); break; }
case ec_cs_get_length: { set_last_float(length_in_seconds_exact()); break; }
case ec_cs_get_length_samples: { set_last_long_integer(length_in_samples()); break; }
case ec_cs_set_length:
{
set_chainsetup_processing_length_in_seconds(first_action_argument_as_float());
break;
}
case ec_cs_set_length_samples:
{
set_chainsetup_processing_length_in_samples(first_action_argument_as_samples());
break;
}
case ec_cs_toggle_loop: { toggle_chainsetup_looping(); break; }
case ec_cs_option:
{
selected_chainsetup_repp->interpret_options(action_arguments_as_vector());
if (selected_chainsetup_repp->interpret_result() != true) {
set_last_error(selected_chainsetup_repp->interpret_result_verbose());
}
break;
}
// ---
// Chains
// ---
case ec_c_add: { add_chains(kvu_string_to_vector(first_action_argument_as_string(), ',')); break; }
case ec_c_remove: { remove_chains(); break; }
case ec_c_list: { set_last_string_list(chain_names()); break; }
case ec_c_select: { select_chains(kvu_string_to_vector(first_action_argument_as_string(), ',')); break; }
case ec_c_selected: { set_last_string_list(selected_chains()); break; }
case ec_c_index_select: { select_chains_by_index(kvu_string_to_int_vector(first_action_argument_as_string(), ',')); break; }
case ec_c_deselect: { deselect_chains(kvu_string_to_vector(first_action_argument_as_string(), ',')); break; }
case ec_c_select_add:
{
select_chains(kvu_string_to_vector(first_action_argument_as_string() + "," +
kvu_vector_to_string(selected_chains(), ","), ','));
break;
}
case ec_c_select_all: { select_all_chains(); break; }
case ec_c_clear: { clear_chains(); break; }
case ec_c_rename:
{
if (selected_chains().size() != 1) {
set_last_error("When renaming chains, only one chain canbe selected.");
}
else {
rename_chain(first_action_argument_as_string());
}
break;
}
case ec_c_muting: { toggle_chain_muting(); break; }
case ec_c_bypass: { toggle_chain_bypass(); break; }
case ec_c_status:
{
set_last_string(chain_status());
break;
}
// ---
// Actions common to audio inputs and outputs
// ---
case ec_aio_status:
case ec_ai_status:
case ec_ao_status:
{
set_last_string(aio_status());
break;
}
case ec_aio_register: { aio_register(); break; }
// ---
// Audio input objects
// ---
case ec_ai_add: { add_audio_input(first_action_argument_as_string()); break; }
case ec_ai_describe: { set_last_string(ECA_OBJECT_FACTORY::audio_object_to_eos(selected_audio_input_repp, "i")); break; }
case ec_ai_remove: { remove_audio_input(); break; }
case ec_ai_list: { set_last_string_list(audio_input_names()); break; }
case ec_ai_select: { select_audio_input(first_action_argument_as_string()); break; }
case ec_ai_selected: { set_last_string(get_audio_input()->label()); break; }
case ec_ai_index_select: {
if (first_action_argument_as_string().size() > 0) {
select_audio_input_by_index(first_action_argument_as_int());
}
break;
}
case ec_ai_attach: { attach_audio_input(); break; }
case ec_ai_forward:
{
audio_input_as_selected();
forward_audio_object(first_action_argument_as_float());
break;
}
case ec_ai_rewind:
{
audio_input_as_selected();
rewind_audio_object(first_action_argument_as_float());
break;
}
case ec_ai_set_position: { audio_input_as_selected(); set_audio_object_position(first_action_argument_as_float()); break; }
case ec_ai_set_position_samples: { audio_input_as_selected(); set_audio_object_position_samples(first_action_argument_as_long_int()); break; }
case ec_ai_get_position: { set_last_float(get_audio_input()->position().seconds()); break; }
case ec_ai_get_position_samples: { set_last_long_integer(get_audio_input()->position().samples()); break; }
case ec_ai_get_length: { set_last_float(get_audio_input()->length().seconds()); break; }
case ec_ai_get_length_samples: { set_last_long_integer(get_audio_input()->length().samples()); break; }
case ec_ai_get_format: {
set_last_string(get_audio_input()->format_string() + "," +
kvu_numtostr(get_audio_input()->channels()) + "," +
kvu_numtostr(get_audio_input()->samples_per_second()));
break;
}
case ec_ai_wave_edit: { audio_input_as_selected(); wave_edit_audio_object(); break; }
// ---
// Audio output objects
// ---
case ec_ao_add: { if (first_action_argument_as_string().size() == 0) add_default_output(); else add_audio_output(first_action_argument_as_string()); break; }
case ec_ao_add_default: { add_default_output(); break; }
case ec_ao_describe: { set_last_string(ECA_OBJECT_FACTORY::audio_object_to_eos(selected_audio_output_repp, "o")); break; }
case ec_ao_remove: { remove_audio_output(); break; }
case ec_ao_list: { set_last_string_list(audio_output_names()); break; }
case ec_ao_select: { select_audio_output(first_action_argument_as_string()); break; }
case ec_ao_selected: { set_last_string(get_audio_output()->label()); break; }
case ec_ao_index_select: {
select_audio_output_by_index(first_action_argument_as_int());
break;
}
case ec_ao_attach: { attach_audio_output(); break; }
case ec_ao_forward:
{
audio_output_as_selected();
forward_audio_object(first_action_argument_as_float());
break;
}
case ec_ao_rewind:
{
audio_output_as_selected();
rewind_audio_object(first_action_argument_as_float());
break;
}
case ec_ao_set_position: { audio_output_as_selected(); set_audio_object_position(first_action_argument_as_float()); break; }
case ec_ao_set_position_samples: { audio_output_as_selected(); set_audio_object_position_samples(first_action_argument_as_long_int()); break; }
case ec_ao_get_position: { set_last_float(get_audio_output()->position().seconds()); break; }
case ec_ao_get_position_samples: { set_last_long_integer(get_audio_output()->position().samples()); break; }
case ec_ao_get_length: { set_last_float(get_audio_output()->length().seconds()); break; }
case ec_ao_get_length_samples: { set_last_long_integer(get_audio_output()->length().samples()); break; }
case ec_ao_get_format: {
set_last_string(get_audio_output()->format_string() + "," +
kvu_numtostr(get_audio_output()->channels()) + "," +
kvu_numtostr(get_audio_output()->samples_per_second()));
break;
}
case ec_ao_wave_edit: { audio_output_as_selected(); wave_edit_audio_object(); break; }
// ---
// Chain operators
// ---
case ec_cop_add: { add_chain_operator(first_action_argument_as_string()); break; }
case ec_cop_describe:
{
const CHAIN_OPERATOR *t = get_chain_operator();
set_last_string(t == 0 ? "" : ECA_OBJECT_FACTORY::chain_operator_to_eos(t));
break;
}
case ec_cop_remove: { remove_chain_operator(); break; }
case ec_cop_list: { set_last_string_list(chain_operator_names()); break; }
case ec_cop_select: { select_chain_operator(first_action_argument_as_int()); break; }
case ec_cop_selected: { set_last_integer(selected_chain_operator()); break; }
case ec_cop_set:
{
vector<string> a = kvu_string_to_vector(first_action_argument_as_string(), ',');
if (a.size() < 3) {
set_last_error("Not enough parameters!");
break;
}
int id1 = atoi(a[0].c_str());
int id2 = atoi(a[1].c_str());
CHAIN_OPERATOR::parameter_t v = atof(a[2].c_str());
bool valid =
action_helper_check_cop_op_args(id1, id2);
if (valid == true) {
select_chain_operator(id1);
select_chain_operator_parameter(id2);
set_chain_operator_parameter(v);
}
// note: helper func sets the error string if needed
break;
}
case ec_cop_get:
{
vector<string> a =
kvu_string_to_vector(first_action_argument_as_string(), ',');
if (a.size() < 2) {
set_last_error("Not enough parameters!");
break;
}
int id1 = atoi(a[0].c_str());
int id2 = atoi(a[1].c_str());
bool valid =
action_helper_check_cop_op_args(id1, id2);
if (valid == true) {
select_chain_operator(id1);
select_chain_operator_parameter(id2);
set_last_float(get_chain_operator_parameter());
}
// note: helper func sets the error string if needed
break;
}
case ec_cop_status:
{
set_last_string(chain_operator_status());
break;
}
// ---
// Chain operator parameters
// ---
case ec_copp_list: { set_last_string_list(chain_operator_parameter_names()); break; }
case ec_copp_select: { select_chain_operator_parameter(first_action_argument_as_int()); break; }
case ec_copp_selected: { set_last_integer(selected_chain_operator_parameter()); break; }
case ec_copp_set: { set_chain_operator_parameter(first_action_argument_as_float()); break; }
case ec_copp_get: { set_last_float(get_chain_operator_parameter()); break; }
// ---
// Controllers
// ---
case ec_ctrl_add: { add_controller(first_action_argument_as_string()); break; }
case ec_ctrl_describe:
{
const GENERIC_CONTROLLER *t = get_controller();
set_last_string(t == 0 ? "" : ECA_OBJECT_FACTORY::controller_to_eos(t));
break;
}
case ec_ctrl_remove: { remove_controller(); break; }
case ec_ctrl_list: { set_last_string_list(controller_names()); break; }
case ec_ctrl_select: { select_controller(first_action_argument_as_int()); break; }
case ec_ctrl_selected: { set_last_integer(selected_controller()); break; }
case ec_ctrl_status:
{
set_last_string(controller_status());
break;
}
case ec_ctrl_get_target: { set_last_integer(selected_controller_target()); break; }
// ---
// Controller parameters
// ---
case ec_ctrlp_list: { set_last_string_list(controller_parameter_names()); break; }
case ec_ctrlp_select: { select_controller_parameter(first_action_argument_as_int()); break; }
case ec_ctrlp_selected: { set_last_integer(selected_controller_parameter()); break; }
case ec_ctrlp_get: { set_last_float(get_controller_parameter()); break; }
case ec_ctrlp_set: { set_controller_parameter(first_action_argument_as_float()); break; }
case ec_cop_register: { cop_register(); break; }
case ec_preset_register: { preset_register(); break; }
case ec_ladspa_register: { ladspa_register(); break; }
case ec_ctrl_register: { ctrl_register(); break; }
case ec_map_cop_list: { cop_descriptions(); break; }
case ec_map_preset_list: { preset_descriptions(); break; }
case ec_map_ladspa_list: { ladspa_descriptions(false); break; }
case ec_map_ladspa_id_list: { ladspa_descriptions(true); break; }
case ec_map_ctrl_list: { ctrl_descriptions(); break; }
// ---
// Engine commands
// ---
case ec_engine_launch: {
if (is_engine_running() != true)
engine_start();
else
set_last_error("Engine already running, use 'engine-halt' first.");
break;
}
case ec_engine_halt: {
if (is_engine_running() == true)
close_engine();
else
set_last_error("Engine not running, use 'engine-launch' first.");
break;
}
case ec_engine_status: { set_last_string(engine_status()); break; }
// ---
// Internal commands
// ---
case ec_int_cmd_list: { set_last_string_list(registered_commands_list()); break; }
case ec_int_log_history: { set_last_string(ECA_LOGGER::instance().log_history()); break; }
case ec_int_output_mode_wellformed: {
ECA_LOGGER::attach_logger(new ECA_LOGGER_WELLFORMED());
wellformed_mode_rep = true;
break;
}
case ec_int_set_float_to_string_precision: { set_float_to_string_precision(first_action_argument_as_int()); break; }
case ec_int_set_log_history_length: { ECA_LOGGER::instance().set_log_history_length(first_action_argument_as_int()); break; }
case ec_int_version_string: { set_last_string(ecasound_library_version); break; }
case ec_int_version_lib_current: { set_last_integer(ecasound_library_version_current); break; }
case ec_int_version_lib_revision: { set_last_integer(ecasound_library_version_revision); break; }
case ec_int_version_lib_age: { set_last_integer(ecasound_library_version_age); break; }
// ---
// Dump commands
// ---
case ec_dump_target: { ctrl_dump_rep.set_dump_target(first_action_argument_as_string()); break; }
case ec_dump_status: { ctrl_dump_rep.dump_status(); break; }
case ec_dump_position: { ctrl_dump_rep.dump_position(); break; }
case ec_dump_length: { ctrl_dump_rep.dump_length(); break; }
case ec_dump_cs_status: { ctrl_dump_rep.dump_chainsetup_status(); break; }
case ec_dump_c_selected: { ctrl_dump_rep.dump_selected_chain(); break; }
case ec_dump_ai_selected: { ctrl_dump_rep.dump_selected_audio_input(); break; }
case ec_dump_ai_position: { ctrl_dump_rep.dump_audio_input_position(); break; }
case ec_dump_ai_length: { ctrl_dump_rep.dump_audio_input_length(); break; }
case ec_dump_ai_open_state: { ctrl_dump_rep.dump_audio_input_open_state(); break; }
case ec_dump_ao_selected: { ctrl_dump_rep.dump_selected_audio_output(); break; }
case ec_dump_ao_position: { ctrl_dump_rep.dump_audio_output_position(); break; }
case ec_dump_ao_length: { ctrl_dump_rep.dump_audio_output_length(); break; }
case ec_dump_ao_open_state: { ctrl_dump_rep.dump_audio_output_open_state(); break; }
case ec_dump_cop_value:
{
vector<string> temp = kvu_string_to_vector(first_action_argument_as_string(), ',');
if (temp.size() > 1) {
ctrl_dump_rep.dump_chain_operator_value(atoi(temp[0].c_str()),
atoi(temp[1].c_str()));
}
break;
}
// ---
// Commands with external dependencies
// ---
#if ECA_COMPILE_JACK
case ec_jack_connect:
{
const vector<string>& params = action_arguments_as_vector();
if (params.size() >= 2)
JACK_CONNECTIONS::connect(params[0].c_str(), params[1].c_str());
break;
}
case ec_jack_disconnect:
{
const vector<string>& params = action_arguments_as_vector();
if (params.size() >= 2)
JACK_CONNECTIONS::disconnect(params[0].c_str(), params[1].c_str());
break;
}
case ec_jack_list_connections:
{
string foo;
if (JACK_CONNECTIONS::list_connections(&foo) == true)
set_last_string(foo);
else
set_last_error("Unable to a list of JACK connections.");
break;
}
#endif
} // <-- switch-case
if (action_reconnect == true) {
if (is_selected() == false ||
is_valid() == false) {
set_last_error("Can't reconnect chainsetup.");
}
else {
connect_chainsetup(0);
if (selected_chainsetup() != connected_chainsetup()) {
set_last_error("Can't reconnect chainsetup.");
}
else {
if (action_restart == true) {
DBC_CHECK(is_running() != true);
start();
}
}
}
}
}
/**
* Executes chainsetup edit on connect chainsetup.
*
* @pre is_connected()
*/
bool ECA_CONTROL::execute_edit_on_connected(const chainsetup_edit_t& edit)
{
DBC_REQUIRE(is_connected() == true);
bool retval = false;
if (is_engine_running() == true) {
ECA_ENGINE::complex_command_t engine_cmd;
engine_cmd.type = ECA_ENGINE::ep_exec_edit;
engine_cmd.m.cs = edit;
engine_repp->command(engine_cmd);
retval = true;
}
else {
/* note: engine not yet running, execute edit directly */
retval = session_repp->connected_chainsetup_repp->execute_edit(edit);
}
return retval;
}
/**
* Executes chainsetup edit on selected chainsetup.
*
* @param edit object specifying the edit action
* @param index if non-negative, override the chainsetup selection
*/
bool ECA_CONTROL::execute_edit_on_selected(const chainsetup_edit_t& edit, int index)
{
bool retval = false;
ECA_CHAINSETUP *csetup = 0;
if (index < 0) {
csetup = selected_chainsetup_repp;
}
else {
if (index >= 0 &&
index < static_cast<int>(session_repp->chainsetups_rep.size())) {
csetup = session_repp->chainsetups_rep[index];
}
}
/* note: make sure that if the selected chainsetup is
* in use by the engine, the edit is performed
* by the engine thread!
*/
if (csetup != 0) {
if (csetup->is_enabled() == true &&
is_engine_running() == true) {
execute_edit_on_connected(edit);
}
else {
csetup->execute_edit(edit);
}
}
return retval;
}
void ECA_CONTROL::print_last_value(struct eci_return_value *retval) const
{
std::string result;
if (retval->type == eci_return_value::retval_error) {
result += "ERROR: ";
}
result += ECA_CONTROL_MAIN::return_value_to_string(retval);
if (wellformed_mode_rep != true) {
if (result.size() > 0)
ECA_LOG_MSG(ECA_LOGGER::eiam_return_values, result);
}
else {
/* in wellformed-output-mode we always create return output */
ECA_LOG_MSG(ECA_LOGGER::eiam_return_values,
std::string(return_value_type_to_string(retval)) +
" " + result);
}
}
string ECA_CONTROL::chainsetup_details_to_string(const ECA_CHAINSETUP* cs) const
{
string result;
vector<CHAIN*>::const_iterator chain_citer;
result += "\n -> Objects..: " + kvu_numtostr(cs->inputs.size());
result += " inputs, " + kvu_numtostr(cs->outputs.size());
result += " outputs, " + kvu_numtostr(cs->chains.size());
result += " chains";
// FIXME: add explanations on why the chainsetup cannot be
// connected
result += "\n -> State....: ";
if (cs->is_locked()) {
result += "connected to engine (engine status: ";
result += engine_status() + ")";
}
else if (cs->is_enabled() && is_engine_created() == true) {
result += "connected (engine status: ";
result += engine_status() + ")";
}
else if (cs->is_enabled())
result += "connected (engine not yet running)";
else if (cs->is_valid())
result += "valid (can be connected)";
else
result += "not valid (cannot be connected)";
result += "\n -> Position.: ";
result += kvu_numtostr(cs->position_in_seconds_exact(), 3);
result += " / ";
if (cs->length_set())
result += kvu_numtostr(cs->length_in_seconds_exact(), 3);
else
result += "inf";
result += "\n -> Options..: ";
result += cs->options_to_string();
for(chain_citer = cs->chains.begin();
chain_citer != cs->chains.end();) {
result += "\n -> Chain \"" + (*chain_citer)->name() + "\": ";
int idx =
(*chain_citer)->connected_input();
if (idx >= 0)
result += ECA_OBJECT_FACTORY::audio_object_to_eos(cs->inputs[idx], "i");
result += " ";
result += (*chain_citer)->to_string();
idx = (*chain_citer)->connected_output();
if (idx >= 0)
result += ECA_OBJECT_FACTORY::audio_object_to_eos(cs->outputs[idx], "o");
++chain_citer;
}
return result;
}
string ECA_CONTROL::chainsetup_status(void) const
{
vector<ECA_CHAINSETUP*>::const_iterator cs_citer = session_repp->chainsetups_rep.begin();
int index = 0;
string result ("### Chainsetup status ###\n");
while(cs_citer != session_repp->chainsetups_rep.end()) {
result += "Chainsetup (" + kvu_numtostr(++index) + ") \"";
result += (*cs_citer)->name() + "\" ";
if (*cs_citer ==
selected_chainsetup_repp)
result += "[selected] ";
if (*cs_citer ==
session_repp->connected_chainsetup_repp)
result += "[connected] ";
if ((*cs_citer == selected_chainsetup_repp) ||
(*cs_citer == session_repp->connected_chainsetup_repp))
result += chainsetup_details_to_string((*cs_citer));
else
result += ": <detailed status omitted -- set as selected to see full status>";
++cs_citer;
if (cs_citer != session_repp->chainsetups_rep.end()) result += "\n";
}
return result;
}
string ECA_CONTROL::chain_status(void) const
{
// --------
DBC_REQUIRE(is_selected() == true);
// --------
MESSAGE_ITEM mitem;
vector<CHAIN*>::const_iterator chain_citer;
const vector<string>& schains = selected_chainsetup_repp->selected_chains();
mitem << "### Chain status (chainsetup '"
<< selected_chainsetup()
<< "') ###\n";
for(chain_citer = selected_chainsetup_repp->chains.begin(); chain_citer != selected_chainsetup_repp->chains.end();) {
mitem << "Chain \"" << (*chain_citer)->name() << "\" ";
if ((*chain_citer)->is_muted()) mitem << "[muted] ";
if ((*chain_citer)->is_processing() == false) mitem << "[bypassed] ";
if (find(schains.begin(), schains.end(), (*chain_citer)->name()) != schains.end()) mitem << "[selected] ";
for(int n = 0; n < (*chain_citer)->number_of_chain_operators(); n++) {
mitem << "\"" << (*chain_citer)->get_chain_operator(n)->name() << "\"";
if (n == (*chain_citer)->number_of_chain_operators()) mitem << " -> ";
}
++chain_citer;
if (chain_citer != selected_chainsetup_repp->chains.end()) mitem << "\n";
}
return mitem.to_string();
}
string ECA_CONTROL::chain_operator_status(void) const
{
// --------
DBC_REQUIRE(is_selected() == true);
// --------
MESSAGE_ITEM msg;
string st_info_string;
vector<CHAIN*>::const_iterator chain_citer = selected_chainsetup_repp->chains.begin();
msg << "### Chain operator status (chainsetup '"
<< selected_chainsetup()
<< "') ###\n";
while(chain_citer != selected_chainsetup_repp->chains.end()) {
msg << "Chain \"" << (*chain_citer)->name() << "\":\n";
for(int p = 0; p < (*chain_citer)->number_of_chain_operators(); p++) {
const CHAIN_OPERATOR* cop = (*chain_citer)->get_chain_operator(p);
msg << "\t" << p + 1 << ". " << cop->name();
for(int n = 0; n < cop->number_of_params(); n++) {
if (n == 0) msg << ": ";
msg << "[" << n + 1 << "] ";
msg << cop->get_parameter_name(n + 1);
msg << " ";
msg << float_to_string(cop->get_parameter(n + 1));
if (n + 1 < cop->number_of_params()) msg << ", ";
}
st_info_string = cop->status();
if (st_info_string.empty() == false) {
msg << "\n\tStatus info:\n" << st_info_string;
}
if (p + 1 < (*chain_citer)->number_of_chain_operators()) msg << "\n";
}
++chain_citer;
if (chain_citer != selected_chainsetup_repp->chains.end()) msg << "\n";
}
return msg.to_string();
}
string ECA_CONTROL::controller_status(void) const
{
// --------
DBC_REQUIRE(is_selected() == true);
// --------
MESSAGE_ITEM mitem;
string st_info_string;
vector<CHAIN*>::const_iterator chain_citer;
mitem << "### Controller status (chainsetup '"
<< selected_chainsetup()
<< "') ###\n";
for(chain_citer = selected_chainsetup_repp->chains.begin(); chain_citer != selected_chainsetup_repp->chains.end();) {
mitem << "Chain \"" << (*chain_citer)->name() << "\":\n";
for(int p = 0; p < (*chain_citer)->number_of_controllers(); p++) {
const GENERIC_CONTROLLER* gtrl = (*chain_citer)->get_controller(p);
mitem << "\t" << p + 1 << ". " << gtrl->name() << ": ";
for(int n = 0; n < gtrl->number_of_params(); n++) {
mitem << "\n\t\t[" << n + 1 << "] ";
mitem << gtrl->get_parameter_name(n + 1);
mitem << " ";
mitem << float_to_string(gtrl->get_parameter(n + 1));
if (n + 1 < gtrl->number_of_params()) mitem << ", ";
}
st_info_string = gtrl->status();
if (st_info_string.empty() == false) {
mitem << "\n\t -- Status info: " << st_info_string;
}
if (p + 1 < (*chain_citer)->number_of_controllers()) mitem << "\n";
}
++chain_citer;
if (chain_citer != selected_chainsetup_repp->chains.end()) mitem << "\n";
}
return mitem.to_string();
}
string ECA_CONTROL::aio_status(void) const
{
// --------
DBC_REQUIRE(is_selected() == true);
// --------
string st_info_string;
vector<AUDIO_IO*>::size_type adev_sizet = 0;
vector<AUDIO_IO*>::const_iterator adev_citer = selected_chainsetup_repp->inputs.begin();
st_info_string += "### Audio input/output status (chainsetup '" +
selected_chainsetup() + "') ###\n";
while(adev_citer != selected_chainsetup_repp->inputs.end()) {
st_info_string += "Input (" + kvu_numtostr(adev_sizet + 1) + "): \"";
for(int n = 0; n < (*adev_citer)->number_of_params(); n++) {
st_info_string += (*adev_citer)->get_parameter(n + 1);
if (n + 1 < (*adev_citer)->number_of_params()) st_info_string += ",";
}
st_info_string += "\" - [" + (*adev_citer)->name() + "]";
if ((*adev_citer) == selected_audio_input_repp) st_info_string += " [selected]";
st_info_string += "\n -> connected to chains \"";
vector<string> temp = selected_chainsetup_repp->get_attached_chains_to_input((selected_chainsetup_repp->inputs)[adev_sizet]);
vector<string>::const_iterator p = temp.begin();
while (p != temp.end()) {
st_info_string += *p;
++p;
if (p != temp.end()) st_info_string += ",";
}
st_info_string += "\": " + (*adev_citer)->status() + "\n";
++adev_sizet;
++adev_citer;
}
adev_sizet = 0;
adev_citer = selected_chainsetup_repp->outputs.begin();
while(adev_citer != selected_chainsetup_repp->outputs.end()) {
st_info_string += "Output (" + kvu_numtostr(adev_sizet + 1) + "): \"";
for(int n = 0; n < (*adev_citer)->number_of_params(); n++) {
st_info_string += (*adev_citer)->get_parameter(n + 1);
if (n + 1 < (*adev_citer)->number_of_params()) st_info_string += ",";
}
st_info_string += "\" - [" + (*adev_citer)->name() + "]";
if ((*adev_citer) == selected_audio_output_repp) st_info_string += " [selected]";
st_info_string += "\n -> connected to chains \"";
vector<string> temp = selected_chainsetup_repp->get_attached_chains_to_output((selected_chainsetup_repp->outputs)[adev_sizet]);
vector<string>::const_iterator p = temp.begin();
while (p != temp.end()) {
st_info_string += *p;
++p;
if (p != temp.end()) st_info_string += ",";
}
st_info_string += "\": ";
st_info_string += (*adev_citer)->status();
++adev_sizet;
++adev_citer;
if (adev_sizet < selected_chainsetup_repp->outputs.size()) st_info_string += "\n";
}
return st_info_string;
}
void ECA_CONTROL::aio_register(void)
{
ECA_LOG_MSG(ECA_LOGGER::info, "Registered audio object types:\n");
string result (eca_aio_register_sub(ECA_OBJECT_FACTORY::audio_io_nonrt_map()));
result += "\n";
result += eca_aio_register_sub(ECA_OBJECT_FACTORY::audio_io_rt_map());
set_last_string(result);
}
static string eca_aio_register_sub(ECA_OBJECT_MAP& objmap)
{
string result;
const list<string>& objlist = objmap.registered_objects();
list<string>::const_iterator p = objlist.begin();
int count = 1;
while(p != objlist.end()) {
string temp;
const AUDIO_IO* q = dynamic_cast<const AUDIO_IO*>(objmap.object_expr(*p));
DBC_CHECK(q != 0);
if (q != 0) {
int params = q->number_of_params();
if (params > 0) {
temp += ": ";
for(int n = 0; n < params; n++) {
temp += q->get_parameter_name(n + 1);
if (n + 1 < params) temp += ",";
}
}
result += kvu_numtostr(count) + ". " + q->name() + ", regex: " +
objmap.keyword_to_expr(*p) + ", params" + temp;
result += "\n";
++count;
}
// else std::cerr << "Failed obj: " << *p << "." << std::endl;
++p;
}
return result;
}
void ECA_CONTROL::cop_register(void)
{
ECA_LOG_MSG(ECA_LOGGER::info, "Registered chain operators:\n");
string result;
const list<string>& objlist = ECA_OBJECT_FACTORY::chain_operator_map().registered_objects();
list<string>::const_iterator p = objlist.begin();
int count = 1;
while(p != objlist.end()) {
string temp;
const CHAIN_OPERATOR* q = dynamic_cast<const CHAIN_OPERATOR*>(ECA_OBJECT_FACTORY::chain_operator_map().object(*p));
if (q != 0) {
int params = q->number_of_params();
for(int n = 0; n < params; n++) {
if (n == 0) temp += ":";
temp += q->get_parameter_name(n + 1);
if (n + 1 < params) temp += ",";
}
result += kvu_numtostr(count) + ". " + q->name() + ", -" + *p + temp;
result += "\n";
++count;
}
++p;
}
set_last_string(result);
}
void ECA_CONTROL::preset_register(void)
{
ECA_LOG_MSG(ECA_LOGGER::info, "Registered effect presets:\n");
string result;
#ifndef ECA_DISABLE_EFFECTS
const list<string>& objlist = ECA_OBJECT_FACTORY::preset_map().registered_objects();
list<string>::const_iterator p = objlist.begin();
int count = 1;
while(p != objlist.end()) {
string temp;
const PRESET* q = dynamic_cast<const PRESET*>(ECA_OBJECT_FACTORY::preset_map().object(*p));
if (q != 0) {
int params = q->number_of_params();
for(int n = 0; n < params; n++) {
if (n == 0) temp += ":";
temp += q->get_parameter_name(n + 1);
if (n + 1 < params) temp += ",";
}
result += kvu_numtostr(count) + ". " + q->name() + ", -pn:" + *p + temp;
result += "\n";
++count;
}
++p;
}
#endif
set_last_string(result);
}
void ECA_CONTROL::ladspa_register(void)
{
ECA_LOG_MSG(ECA_LOGGER::info, "Registered LADSPA plugins:\n");
string result;
#ifndef ECA_DISABLE_EFFECTS
const list<string>& objlist = ECA_OBJECT_FACTORY::ladspa_plugin_map().registered_objects();
list<string>::const_iterator p = objlist.begin();
int count = 1;
while(p != objlist.end()) {
const EFFECT_LADSPA* q = dynamic_cast<const EFFECT_LADSPA*>(ECA_OBJECT_FACTORY::ladspa_plugin_map().object(*p));
if (q != 0) {
string temp = "\n\t-el:" + q->unique() + ",";
int params = q->number_of_params();
for(int n = 0; n < params; n++) {
temp += "'" + q->get_parameter_name(n + 1) + "'";
if (n + 1 < params) temp += ",";
}
result += kvu_numtostr(count) + ". " + q->name() + "" + temp;
result += "\n";
++count;
}
++p;
}
#endif
set_last_string(result);
}
void ECA_CONTROL::ctrl_register(void)
{
ECA_LOG_MSG(ECA_LOGGER::info, "Registered controllers:\n");
string result;
const list<string>& objlist = ECA_OBJECT_FACTORY::controller_map().registered_objects();
list<string>::const_iterator p = objlist.begin();
int count = 1;
while(p != objlist.end()) {
string temp;
const GENERIC_CONTROLLER* q = dynamic_cast<const GENERIC_CONTROLLER*>(ECA_OBJECT_FACTORY::controller_map().object(*p));
if (q != 0) {
int params = q->number_of_params();
for(int n = 0; n < params; n++) {
if (n == 0) temp += ":";
temp += q->get_parameter_name(n + 1);
if (n + 1 < params) temp += ",";
}
result += kvu_numtostr(count) + ". " + q->name() + ", -" + *p +
temp;
result += "\n";
++count;
}
++p;
}
set_last_string(result);
}
/**
* Print description of all chain operators and
* their parameters.
*/
void ECA_CONTROL::operator_descriptions_helper(const ECA_OBJECT_MAP& arg, string* result)
{
/* switch to "C" locale to avoid strange floating point
* presentations that could break the output format
* (for example "a,b" insteof of "a.b" */
#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
string old_locale (setlocale(LC_ALL, "C"));
#endif
const list<string>& objlist = arg.registered_objects();
list<string>::const_iterator p = objlist.begin();
int count = 1;
while(p != objlist.end()) {
string temp;
const OPERATOR* q = dynamic_cast<const OPERATOR*>(arg.object(*p));
if (q != 0) {
/* FIXME: prefer backslash escaped over '_' to handle commas */
/* 1. keyword */
*result += kvu_string_search_and_replace(*p, ',', '_');
/* 2. name */
*result += "," + kvu_string_search_and_replace(q->name(), ',', '_');
/* 3. description */
*result += "," + kvu_string_search_and_replace(q->description(), ',', '_');
int params = q->number_of_params();
/* 4. number of params */
*result += "," + kvu_numtostr(params);
/* 5. description of params (for all params) */
for(int n = 0; n < params; n++) {
struct OPERATOR::PARAM_DESCRIPTION pd;
q->parameter_description(n + 1, &pd);
/* 5.1 name of param */
*result += "," + kvu_string_search_and_replace(q->get_parameter_name(n + 1), ',', '_');
/* 5.2 description */
*result += "," + kvu_string_search_and_replace(pd.description, ',', '_');
/* 5.3 default value */
*result += "," + float_to_string(pd.default_value);
/* 5.4 is bounded above (1=yes, 0=no) */
*result += ",above=" + kvu_numtostr(static_cast<int>(pd.bounded_above));
/* 5.5 upper bound */
*result += ",upper=" + float_to_string(pd.upper_bound);
/* 5.6 is bounded below (1=yes, 0=no) */
*result += ",below=" + kvu_numtostr(static_cast<int>(pd.bounded_below));
/* 5.7 lower bound */
*result += ",lower=" + float_to_string(pd.lower_bound);
/* 5.8. is toggled (1=yes, 0=no) */
*result += "," + kvu_numtostr(static_cast<int>(pd.toggled));
/* 5.9. is integer value (1=yes, 0=no) */
*result += "," + kvu_numtostr(static_cast<int>(pd.integer));
/* 5.10. is logarithmis value (1=yes, 0=no) */
*result += "," + kvu_numtostr(static_cast<int>(pd.logarithmic));
/* 5.11. is output value (1=yes, 0=no) */
*result += ",output=" + kvu_numtostr(static_cast<int>(pd.output));
}
*result += "\n";
++count;
}
++p;
}
/* see above */
#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
setlocale(LC_ALL, old_locale.c_str());
#endif
}
/**
* Print the description of all chain operators and
* their parameters.
*/
void ECA_CONTROL::cop_descriptions(void)
{
string result;
operator_descriptions_helper(ECA_OBJECT_FACTORY::chain_operator_map(), &result);
set_last_string(result);
}
/**
* Prints the description of all effect presets and
* their parameters.
*/
void ECA_CONTROL::preset_descriptions(void)
{
string result;
operator_descriptions_helper(ECA_OBJECT_FACTORY::preset_map(), &result);
set_last_string(result);
}
/**
* Prints the description of all LADSPA plugins and
* their parameters.
*/
void ECA_CONTROL::ladspa_descriptions(bool use_id)
{
string result;
if (use_id) {
operator_descriptions_helper(ECA_OBJECT_FACTORY::ladspa_plugin_id_map(), &result);
}
else {
operator_descriptions_helper(ECA_OBJECT_FACTORY::ladspa_plugin_map(), &result);
}
set_last_string(result);
}
/**
* Print the description of all controllers and
* their parameters.
*/
void ECA_CONTROL::ctrl_descriptions(void)
{
string result;
operator_descriptions_helper(ECA_OBJECT_FACTORY::controller_map(), &result);
set_last_string(result);
}