1 // ------------------------------------------------------------------------
2 // eca-control.cpp: Class for controlling the whole ecasound library
3 // Copyright (C) 1999-2005,2008,2009,2012 Kai Vehmanen
4 // Copyright (C) 2005 Stuart Allie
5 // Copyright (C) 2009 Adam Linson
6 //
7 // Attributes:
8 // eca-style-version: 3 (see Ecasound Programmer's Guide)
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 // ------------------------------------------------------------------------
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <cassert>
29 #include <iostream>
30 #include <fstream>
31 #include <string>
32 #include <vector>
33 #include <list>
34 #include <algorithm>
35 #include <unistd.h>
36
37 #ifdef HAVE_LOCALE_H
38 #include <locale.h>
39 #endif
40
41 #include <kvu_utils.h> /* string_to_vector(), string_to_int_vector() */
42 #include <kvu_value_queue.h>
43 #include <kvu_message_item.h>
44 #include <kvu_dbc.h>
45 #include <kvu_numtostr.h>
46
47 #include "audioio.h"
48 #include "eca-chain.h"
49 #include "eca-chainop.h"
50 #include "eca-chainsetup.h"
51 #include "eca-control.h"
52 #include "eca-control-main.h"
53 #include "eca-engine.h"
54 #include "eca-object-factory.h"
55 #include "eca-object-map.h"
56 #include "eca-preset-map.h"
57 #include "eca-session.h"
58
59 #include "generic-controller.h"
60 #include "eca-chainop.h"
61 #include "audiofx_ladspa.h"
62 #include "audiofx_lv2.h"
63 #include "preset.h"
64 #include "sample-specs.h"
65 #include "jack-connections.h"
66
67 #include "eca-version.h"
68 #include "eca-error.h"
69 #include "eca-logger.h"
70 #include "eca-logger-wellformed.h"
71
72 /**
73 * Import namespaces
74 */
75 using std::string;
76 using std::list;
77 using std::vector;
78 using std::cerr;
79 using std::endl;
80 using namespace ECA;
81
82 /**
83 * Declarations for private static functions
84 */
85 static string eca_aio_register_sub(ECA_OBJECT_MAP& objmap);
86
87 /**
88 * Definitions for member functions
89 */
90
ECA_CONTROL(ECA_SESSION * psession)91 ECA_CONTROL::ECA_CONTROL (ECA_SESSION* psession)
92 : ctrl_dump_rep(this),
93 wellformed_mode_rep(false)
94 {
95 ECA_LOG_MSG(ECA_LOGGER::system_objects, "ECA_CONTROL constructor");
96
97 session_repp = psession;
98 selected_chainsetup_repp = psession->selected_chainsetup_repp;
99 engine_repp = 0;
100 engine_pid_rep = -1;
101 engine_exited_rep.set(0);
102 float_to_string_precision_rep = 3;
103 joining_rep = false;
104 DBC_CHECK(is_engine_created() != true);
105
106 selected_audio_object_repp = 0;
107 selected_audio_input_repp = 0;
108 selected_audio_output_repp = 0;
109 }
110
~ECA_CONTROL(void)111 ECA_CONTROL::~ECA_CONTROL(void)
112 {
113 ECA_LOG_MSG(ECA_LOGGER::system_objects, "ECA_CONTROL destructor");
114 close_engine();
115 }
116
fill_command_retval(struct eci_return_value * retval) const117 void ECA_CONTROL::fill_command_retval(struct eci_return_value *retval) const
118 {
119 if (retval == 0)
120 return;
121
122 *retval = last_retval_rep;
123 }
124
command(const string & cmd_and_args,struct eci_return_value * retval)125 void ECA_CONTROL::command(const string& cmd_and_args, struct eci_return_value *retval)
126 {
127 clear_last_values();
128 clear_action_arguments();
129
130 ECA_LOG_MSG(ECA_LOGGER::user_objects, "processing cmd and arg: " + cmd_and_args);
131
132 vector<string> tokens = kvu_string_to_tokens_quoted(cmd_and_args);
133 vector<string>::iterator cmd = tokens.begin();
134 if (cmd != tokens.end()) {
135 const std::map<std::string,int>& cmdmap = ECA_IAMODE_PARSER::registered_commands();
136 if (cmdmap.find(*cmd) == cmdmap.end()) {
137 // ---
138 // *p is not recognized as a iamode command
139 // ---
140 if (cmd->size() > 0 && (*cmd)[0] == '-') {
141 // 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;
142 if (*cmd == "-i")
143 ECA_LOG_MSG(ECA_LOGGER::info,
144 "WARNING: syntax variant '-i file.ext' not supported, please use 'ai-add file.ext' instead.");
145 else if (*cmd == "-o")
146 ECA_LOG_MSG(ECA_LOGGER::info,
147 "WARNING: syntax variant '-o file.ext' not supported, please use 'ai-add file.ext' instead.");
148 else {
149 ECA_LOG_MSG(ECA_LOGGER::user_objects, "passiong to cs-option: " + cmd_and_args);
150 chainsetup_option(cmd_and_args);
151 }
152 }
153 else {
154 set_last_error("Unknown command!");
155 }
156 }
157 else {
158 int action_id = ECA_IAMODE_PARSER::command_to_action_id(*cmd);
159 if (action_id == ec_help) {
160 show_controller_help();
161 }
162 else {
163 vector<string>::iterator args = cmd + 1;
164 if (args != tokens.end()) {
165 set_action_argument(vector<string> (args, tokens.end()));
166 }
167 action(action_id);
168 }
169 }
170 }
171
172 fill_command_retval(retval);
173 }
174
set_action_argument(const string & s)175 void ECA_CONTROL::set_action_argument(const string& s)
176 {
177 action_args_rep.resize(0);
178 action_args_rep.push_back(s);
179 action_arg_f_set_rep = false;
180 }
181
set_action_argument(const std::vector<std::string> & s)182 void ECA_CONTROL::set_action_argument(const std::vector<std::string>& s)
183 {
184 action_args_rep = s;
185 action_arg_f_set_rep = false;
186 }
187
set_action_argument(double v)188 void ECA_CONTROL::set_action_argument(double v)
189 {
190 action_arg_f_rep = v;
191 action_arg_f_set_rep = true;
192 }
193
clear_action_arguments(void)194 void ECA_CONTROL::clear_action_arguments(void)
195 {
196 // use resize() instead of clear(); clear() was a late
197 // addition to C++ standard and not supported by all
198 // compilers (for example egcs-2.91.66)
199 action_args_rep.resize(0);
200
201 action_arg_f_rep = 0.0f;
202 action_arg_f_set_rep = false;
203 }
204
first_action_argument_as_float(void) const205 double ECA_CONTROL::first_action_argument_as_float(void) const
206 {
207 if (action_arg_f_set_rep == true)
208 return action_arg_f_rep;
209
210 if (action_args_rep.size() == 0)
211 return 0.0f;
212
213 return atof(action_args_rep[0].c_str());
214 }
215
first_action_argument_as_string(void) const216 string ECA_CONTROL::first_action_argument_as_string(void) const
217 {
218 if (action_args_rep.size() == 0)
219 return std::string();
220
221 return action_args_rep[0];
222 }
223
action_arguments_as_vector(void) const224 const vector<string>& ECA_CONTROL::action_arguments_as_vector(void) const
225 {
226 return action_args_rep;
227 }
228
first_action_argument_as_int(void) const229 int ECA_CONTROL::first_action_argument_as_int(void) const
230 {
231 if (action_args_rep.size() == 0)
232 return 0;
233
234 return atoi(action_args_rep[0].c_str());
235 }
236
first_action_argument_as_long_int(void) const237 long int ECA_CONTROL::first_action_argument_as_long_int(void) const
238 {
239 if (action_args_rep.size() == 0)
240 return 0;
241
242 return atol(action_args_rep[0].c_str());
243 }
244
first_action_argument_as_samples(void) const245 SAMPLE_SPECS::sample_pos_t ECA_CONTROL::first_action_argument_as_samples(void) const
246 {
247 if (action_args_rep.size() == 0)
248 return 0;
249
250 #ifdef HAVE_ATOLL
251 return atoll(action_args_rep[0].c_str());
252 #else
253 return atol(action_args_rep[0].c_str());
254 #endif
255 }
256
command_float_arg(const string & cmd,double arg,struct eci_return_value * retval)257 void ECA_CONTROL::command_float_arg(const string& cmd, double arg, struct eci_return_value *retval)
258 {
259 clear_action_arguments();
260 set_action_argument(arg);
261 int action_id = ec_unknown;
262 action_id = ECA_IAMODE_PARSER::command_to_action_id(cmd);
263 action(action_id);
264 fill_command_retval(retval);
265 }
266
267 /**
268 * Interprets an EOS (ecasound optiont syntax) token (prefixed with '-').
269 */
chainsetup_option(const string & cmd)270 void ECA_CONTROL::chainsetup_option(const string& cmd)
271 {
272 string prefix = kvu_get_argument_prefix(cmd);
273 if (prefix == "el" || prefix == "pn") { // --- LADSPA plugins and presets
274 if (selected_chains().size() == 1)
275 add_chain_operator(cmd);
276 else
277 set_last_error("When adding chain operators, only one chain can be selected.");
278 }
279 else if (ECA_OBJECT_FACTORY::chain_operator_map().object(prefix) != 0) {
280 if (selected_chains().size() == 1)
281 add_chain_operator(cmd);
282 else
283 set_last_error("When adding chain operators, only one chain can be selected.");
284 }
285 else if (ECA_OBJECT_FACTORY::controller_map().object(prefix) != 0) {
286 if (selected_chains().size() == 1)
287 add_controller(cmd);
288 else
289 set_last_error("When adding controllers, only one chain can be selected.");
290 }
291 else {
292 set_action_argument(cmd);
293 action(ec_cs_option);
294 }
295 }
296
297 /**
298 * Checks action preconditions.
299 *
300 * @return Sets status of private data members 'action_ok',
301 * 'action_restart', and 'action_reconnect'.
302 */
check_action_preconditions(int action_id)303 void ECA_CONTROL::check_action_preconditions(int action_id)
304 {
305 action_ok = true;
306 action_reconnect = false;
307 action_restart = false;
308
309 /* case 1: action requiring arguments, but not arguments available */
310 if (action_arg_f_set_rep == false &&
311 first_action_argument_as_string().size() == 0 &&
312 action_requires_params(action_id)) {
313 set_last_error("Can't perform requested action; argument omitted.");
314 action_ok = false;
315 }
316 /* case 2: action requires an audio input, but no input available */
317 else if (is_selected() == true &&
318 get_audio_input() == 0 &&
319 action_requires_selected_audio_input(action_id)) {
320 set_last_error("Can't perform requested action; no audio input selected.");
321 action_ok = false;
322 }
323 /* case 3: action requires an audio output, but no output available */
324 else if (is_selected() == true &&
325 get_audio_output() == 0 &&
326 action_requires_selected_audio_output(action_id)) {
327 set_last_error("Can't perform requested action; no audio output selected.");
328 action_ok = false;
329 }
330 /* case 4: action requires a select chainsetup, but none selected */
331 else if (is_selected() == false &&
332 action_requires_selected(action_id)) {
333 if (!is_connected()) {
334 set_last_error("Can't perform requested action; no chainsetup selected.");
335 action_ok = false;
336 }
337 else {
338 ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: No chainsetup selected. Connected chainsetup will be selected.");
339 select_chainsetup(connected_chainsetup());
340 }
341 }
342 /* case 5: action requires a connected chainsetup, but none connected */
343 else if (is_connected() == false &&
344 action_requires_connected(action_id)) {
345 if (!is_selected()) {
346 set_last_error("Can't perform requested action; no chainsetup connected.");
347 action_ok = false;
348 }
349 else {
350 if (is_valid() == true) {
351 ECA_LOG_MSG(ECA_LOGGER::info,
352 "NOTE: No chainsetup connected. Trying to connect currently selected chainsetup \""
353 + selected_chainsetup_repp->name()
354 + "\"");
355 connect_chainsetup(0);
356 }
357 if (is_connected() != true) {
358 /* connect_chainsetup() sets last_error() so we just add to it */
359 set_last_error(last_error() + " Selected chainsetup cannot be connected. Can't perform requested action. ");
360 action_ok = false;
361 }
362 }
363 }
364 /* case 6: action can't be performed on a connected setup,
365 * but selected chainsetup is also connected */
366 else if (selected_chainsetup() == connected_chainsetup() &&
367 action_requires_selected_not_connected(action_id)) {
368 ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: This operation requires that chainsetup is disconnected. Temporarily disconnecting...");
369 if (is_running()) action_restart = true;
370 disconnect_chainsetup();
371 action_reconnect = true;
372 }
373 }
374
action(int action_id,const vector<string> & args)375 void ECA_CONTROL::action(int action_id,
376 const vector<string>& args)
377 {
378 ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: ECA_CONTROL::action() method is obsolete.\n");
379 clear_action_arguments();
380 set_action_argument(kvu_vector_to_string(args, " "));
381 action(action_id);
382 }
383
action_helper_check_cop_op_args(int copid,int coppid)384 bool ECA_CONTROL::action_helper_check_cop_op_args(int copid, int coppid)
385 {
386 DBC_REQUIRE(is_selected() == true);
387
388 const vector<string>& selchains =
389 selected_chainsetup_repp->selected_chains();
390 bool res = false;
391
392 if (selchains.size() == 0) {
393 set_last_error("No chain selected, unable to identify chainop");
394 }
395 else if (selchains.size() > 1) {
396 set_last_error("More than one chain selected, unable to identify chainop");
397 }
398 else {
399 const CHAIN* selch =
400 selected_chainsetup_repp->get_chain_with_name(selchains[0]);
401 if (copid < 1 || copid > selch->number_of_chain_operators()) {
402 set_last_error("Invalid chainop-id, unable to identify chainop");
403 }
404 else if (coppid < 1) {
405 set_last_error("Invalid copp-id, indexing starts from 1.");
406 }
407 else {
408 res = true;
409 }
410 }
411
412 return res;
413 }
414
action(int action_id)415 void ECA_CONTROL::action(int action_id)
416 {
417 clear_last_values();
418 check_action_preconditions(action_id);
419
420 if (action_ok != true) return;
421
422 switch(action_id) {
423 case ec_unknown: { set_last_error("Unknown command!"); break; }
424
425 // ---
426 // General
427 // ---
428 case ec_exit: { quit(); break; }
429 case ec_start:
430 {
431 if (is_running() != true) {
432 int result = start();
433 if (result < 0) {
434 set_last_error("Error, unable to start processing");
435 }
436 }
437 // ECA_LOG_MSG(ECA_LOGGER::info, "Can't perform requested action; no chainsetup connected.");
438 break;
439 }
440 case ec_stop: { if (is_engine_created()) stop(); break; }
441 case ec_stop_sync: { if (is_engine_created()) stop_on_condition(); break; }
442 case ec_run:
443 {
444 int result = run();
445 if (result < 0) {
446 set_last_error("Errors during processing");
447 }
448 break;
449 }
450 case ec_debug:
451 {
452 int level = first_action_argument_as_int();
453 ECA_LOGGER::instance().set_log_level_bitmask(level);
454 set_last_string("Debug level set to " + kvu_numtostr(level) + ".");
455 break;
456 }
457 case ec_resource_file:
458 {
459 session_repp->interpret_general_option(string("-R:") +
460 first_action_argument_as_string());
461 break;
462 }
463
464 // ---
465 // Chainsetups
466 // ---
467 case ec_cs_add:
468 {
469 add_chainsetup(first_action_argument_as_string());
470 break;
471 }
472 case ec_cs_remove: { remove_chainsetup(); break; }
473 case ec_cs_list: { set_last_string_list(chainsetup_names()); break; }
474 case ec_cs_select: { select_chainsetup(first_action_argument_as_string()); break; }
475 case ec_cs_selected: { set_last_string(selected_chainsetup()); break; }
476 case ec_cs_index_select: {
477 if (first_action_argument_as_string().size() > 0) {
478 select_chainsetup_by_index(first_action_argument_as_int());
479 }
480 break;
481 }
482 case ec_cs_edit: { edit_chainsetup(); break; }
483 case ec_cs_load: { load_chainsetup(first_action_argument_as_string()); break; }
484 case ec_cs_save: { save_chainsetup(""); break; }
485 case ec_cs_save_as: { save_chainsetup(first_action_argument_as_string()); break; }
486 case ec_cs_is_valid: {
487 if (is_valid() == true)
488 set_last_integer(1);
489 else
490 set_last_integer(0);
491 break;
492 }
493 case ec_cs_connect:
494 {
495 if (is_valid() != false) {
496 connect_chainsetup(0);
497 }
498 else {
499 set_last_error("Can't connect; chainsetup not valid!");
500 }
501 break;
502 }
503 case ec_cs_connected: { set_last_string(connected_chainsetup()); break; }
504 case ec_cs_disconnect: { disconnect_chainsetup(); break; }
505 case ec_cs_set_param: { set_chainsetup_parameter(first_action_argument_as_string()); break; }
506 case ec_cs_set_audio_format: { set_chainsetup_sample_format(first_action_argument_as_string()); break; }
507 case ec_cs_status: {
508 set_last_string(chainsetup_status());
509 break;
510 }
511 case ec_cs_rewind: { change_chainsetup_position(-first_action_argument_as_float()); break; }
512 case ec_cs_forward: { change_chainsetup_position(first_action_argument_as_float()); break; }
513 case ec_cs_set_position: { set_chainsetup_position(first_action_argument_as_float()); break; }
514 case ec_cs_set_position_samples: { set_chainsetup_position_samples(first_action_argument_as_samples()); break; }
515 case ec_cs_get_position: { set_last_float(position_in_seconds_exact()); break; }
516 case ec_cs_get_position_samples: { set_last_long_integer(selected_chainsetup_repp->position_in_samples()); break; }
517 case ec_cs_get_length: { set_last_float(length_in_seconds_exact()); break; }
518 case ec_cs_get_length_samples: { set_last_long_integer(length_in_samples()); break; }
519 case ec_cs_set_length:
520 {
521 set_chainsetup_processing_length_in_seconds(first_action_argument_as_float());
522 break;
523 }
524 case ec_cs_set_length_samples:
525 {
526 set_chainsetup_processing_length_in_samples(first_action_argument_as_samples());
527 break;
528 }
529 case ec_cs_toggle_loop: { toggle_chainsetup_looping(); break; }
530 case ec_cs_option:
531 {
532 selected_chainsetup_repp->interpret_options(action_arguments_as_vector());
533 if (selected_chainsetup_repp->interpret_result() != true) {
534 set_last_error(selected_chainsetup_repp->interpret_result_verbose());
535 }
536 break;
537 }
538
539 // ---
540 // Chains
541 // ---
542 case ec_c_add: { add_chains(kvu_string_to_vector(first_action_argument_as_string(), ',')); break; }
543 case ec_c_remove: { remove_chains(); break; }
544 case ec_c_list: { set_last_string_list(chain_names()); break; }
545 case ec_c_select: { select_chains(kvu_string_to_vector(first_action_argument_as_string(), ',')); break; }
546 case ec_c_selected: { set_last_string_list(selected_chains()); break; }
547 case ec_c_index_select: { select_chains_by_index(kvu_string_to_int_vector(first_action_argument_as_string(), ',')); break; }
548 case ec_c_deselect: { deselect_chains(kvu_string_to_vector(first_action_argument_as_string(), ',')); break; }
549 case ec_c_select_add:
550 {
551 select_chains(kvu_string_to_vector(first_action_argument_as_string() + "," +
552 kvu_vector_to_string(selected_chains(), ","), ','));
553 break;
554 }
555 case ec_c_select_all: { select_all_chains(); break; }
556 case ec_c_clear: { clear_chains(); break; }
557 case ec_c_rename:
558 {
559 if (selected_chains().size() != 1) {
560 set_last_error("When renaming chains, only one chain canbe selected.");
561 }
562 else {
563 rename_chain(first_action_argument_as_string());
564 }
565 break;
566 }
567 case ec_c_muting: { set_chain_muting(first_action_argument_as_string()); break; }
568 case ec_c_bypass: { set_chain_bypass(first_action_argument_as_string()); break; }
569 case ec_c_status:
570 {
571 set_last_string(chain_status());
572 break;
573 }
574 case ec_c_is_bypassed: { set_last_integer(chain_is_bypassed()); break; }
575 case ec_c_is_muted: { set_last_integer(chain_is_muted()); break; }
576
577 // ---
578 // Actions common to audio inputs and outputs
579 // ---
580 case ec_aio_status:
581 case ec_ai_status:
582 case ec_ao_status:
583 {
584 set_last_string(aio_status());
585 break;
586 }
587 case ec_aio_register: { aio_register(); break; }
588
589 // ---
590 // Audio input objects
591 // ---
592 case ec_ai_add: { add_audio_input(first_action_argument_as_string()); break; }
593 case ec_ai_describe: { set_last_string(ECA_OBJECT_FACTORY::audio_object_to_eos(selected_audio_input_repp, "i")); break; }
594 case ec_ai_remove: { remove_audio_input(); break; }
595 case ec_ai_list: { set_last_string_list(audio_input_names()); break; }
596 case ec_ai_select: { select_audio_input(first_action_argument_as_string()); break; }
597 case ec_ai_selected: { set_last_string(get_audio_input()->label()); break; }
598 case ec_ai_index_select: {
599 if (first_action_argument_as_string().size() > 0) {
600 select_audio_input_by_index(first_action_argument_as_int());
601 }
602 break;
603 }
604 case ec_ai_attach: { attach_audio_input(); break; }
605 case ec_ai_forward:
606 {
607 audio_input_as_selected();
608 forward_audio_object(first_action_argument_as_float());
609 break;
610 }
611 case ec_ai_rewind:
612 {
613 audio_input_as_selected();
614 rewind_audio_object(first_action_argument_as_float());
615 break;
616 }
617 case ec_ai_set_position: { audio_input_as_selected(); set_audio_object_position(first_action_argument_as_float()); break; }
618 case ec_ai_set_position_samples: { audio_input_as_selected(); set_audio_object_position_samples(first_action_argument_as_long_int()); break; }
619 case ec_ai_get_position: { set_last_float(get_audio_input()->position().seconds()); break; }
620 case ec_ai_get_position_samples: { set_last_long_integer(get_audio_input()->position().samples()); break; }
621 case ec_ai_get_length: { set_last_float(get_audio_input()->length().seconds()); break; }
622 case ec_ai_get_length_samples: { set_last_long_integer(get_audio_input()->length().samples()); break; }
623 case ec_ai_get_format: {
624 set_last_string(get_audio_input()->format_string() + "," +
625 kvu_numtostr(get_audio_input()->channels()) + "," +
626 kvu_numtostr(get_audio_input()->samples_per_second()));
627
628 break;
629 }
630
631 case ec_ai_wave_edit: { audio_input_as_selected(); wave_edit_audio_object(); break; }
632
633 // ---
634 // Audio output objects
635 // ---
636 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; }
637 case ec_ao_add_default: { add_default_output(); break; }
638 case ec_ao_describe: { set_last_string(ECA_OBJECT_FACTORY::audio_object_to_eos(selected_audio_output_repp, "o")); break; }
639 case ec_ao_remove: { remove_audio_output(); break; }
640 case ec_ao_list: { set_last_string_list(audio_output_names()); break; }
641 case ec_ao_select: { select_audio_output(first_action_argument_as_string()); break; }
642 case ec_ao_selected: { set_last_string(get_audio_output()->label()); break; }
643 case ec_ao_index_select: {
644 select_audio_output_by_index(first_action_argument_as_int());
645 break;
646 }
647 case ec_ao_attach: { attach_audio_output(); break; }
648 case ec_ao_forward:
649 {
650 audio_output_as_selected();
651 forward_audio_object(first_action_argument_as_float());
652 break;
653 }
654 case ec_ao_rewind:
655 {
656 audio_output_as_selected();
657 rewind_audio_object(first_action_argument_as_float());
658 break;
659 }
660 case ec_ao_set_position: { audio_output_as_selected(); set_audio_object_position(first_action_argument_as_float()); break; }
661 case ec_ao_set_position_samples: { audio_output_as_selected(); set_audio_object_position_samples(first_action_argument_as_long_int()); break; }
662 case ec_ao_get_position: { set_last_float(get_audio_output()->position().seconds()); break; }
663 case ec_ao_get_position_samples: { set_last_long_integer(get_audio_output()->position().samples()); break; }
664 case ec_ao_get_length: { set_last_float(get_audio_output()->length().seconds()); break; }
665 case ec_ao_get_length_samples: { set_last_long_integer(get_audio_output()->length().samples()); break; }
666 case ec_ao_get_format: {
667 set_last_string(get_audio_output()->format_string() + "," +
668 kvu_numtostr(get_audio_output()->channels()) + "," +
669 kvu_numtostr(get_audio_output()->samples_per_second()));
670 break;
671 }
672 case ec_ao_wave_edit: { audio_output_as_selected(); wave_edit_audio_object(); break; }
673
674 // ---
675 // Chain operators
676 // ---
677 case ec_cop_add: { add_chain_operator(first_action_argument_as_string()); break; }
678 case ec_cop_bypass: { bypass_chain_operator(first_action_argument_as_string()); break; }
679 case ec_cop_describe:
680 {
681 const CHAIN_OPERATOR *t = get_chain_operator();
682 set_last_string(t == 0 ? "" : ECA_OBJECT_FACTORY::chain_operator_to_eos(t));
683 break;
684 }
685 case ec_cop_remove: { remove_chain_operator(); break; }
686 case ec_cop_list: { set_last_string_list(chain_operator_names()); break; }
687 case ec_cop_is_bypassed: { set_last_integer(chain_operator_is_bypassed()); break; }
688 case ec_cop_select: { select_chain_operator(first_action_argument_as_int()); break; }
689 case ec_cop_selected: { set_last_integer(selected_chain_operator()); break; }
690 case ec_cop_set:
691 {
692 vector<string> a = kvu_string_to_vector(first_action_argument_as_string(), ',');
693 if (a.size() < 3) {
694 set_last_error("Not enough parameters!");
695 break;
696 }
697 int id1 = atoi(a[0].c_str());
698 int id2 = atoi(a[1].c_str());
699 CHAIN_OPERATOR::parameter_t v = atof(a[2].c_str());
700
701 bool valid =
702 action_helper_check_cop_op_args(id1, id2);
703 if (valid == true) {
704 select_chain_operator(id1);
705 select_chain_operator_parameter(id2);
706 set_chain_operator_parameter(v);
707 }
708 // note: helper func sets the error string if needed
709 break;
710 }
711 case ec_cop_get:
712 {
713 vector<string> a =
714 kvu_string_to_vector(first_action_argument_as_string(), ',');
715 if (a.size() < 2) {
716 set_last_error("Not enough parameters!");
717 break;
718 }
719 int id1 = atoi(a[0].c_str());
720 int id2 = atoi(a[1].c_str());
721 bool valid =
722 action_helper_check_cop_op_args(id1, id2);
723 if (valid == true) {
724 select_chain_operator(id1);
725 select_chain_operator_parameter(id2);
726 set_last_float(get_chain_operator_parameter());
727 }
728 // note: helper func sets the error string if needed
729 break;
730 }
731
732 case ec_cop_status:
733 {
734 set_last_string(chain_operator_status());
735 break;
736 }
737
738 // ---
739 // Chain operator parameters
740 // ---
741 case ec_copp_list: { set_last_string_list(chain_operator_parameter_names()); break; }
742 case ec_copp_select: { select_chain_operator_parameter(first_action_argument_as_int()); break; }
743 case ec_copp_selected: { set_last_integer(selected_chain_operator_parameter()); break; }
744 case ec_copp_set: { set_chain_operator_parameter(first_action_argument_as_float()); break; }
745 case ec_copp_get: { set_last_float(get_chain_operator_parameter()); break; }
746
747 // ---
748 // Controllers
749 // ---
750 case ec_ctrl_add: { add_controller(first_action_argument_as_string()); break; }
751 case ec_ctrl_describe:
752 {
753 const GENERIC_CONTROLLER *t = get_controller();
754 set_last_string(t == 0 ? "" : ECA_OBJECT_FACTORY::controller_to_eos(t));
755 break;
756 }
757 case ec_ctrl_remove: { remove_controller(); break; }
758 case ec_ctrl_list: { set_last_string_list(controller_names()); break; }
759 case ec_ctrl_select: { select_controller(first_action_argument_as_int()); break; }
760 case ec_ctrl_selected: { set_last_integer(selected_controller()); break; }
761 case ec_ctrl_status:
762 {
763 set_last_string(controller_status());
764 break;
765 }
766 case ec_ctrl_get_target: { set_last_integer(selected_controller_target()); break; }
767
768 // ---
769 // Controller parameters
770 // ---
771 case ec_ctrlp_list: { set_last_string_list(controller_parameter_names()); break; }
772 case ec_ctrlp_select: { select_controller_parameter(first_action_argument_as_int()); break; }
773 case ec_ctrlp_selected: { set_last_integer(selected_controller_parameter()); break; }
774 case ec_ctrlp_get: { set_last_float(get_controller_parameter()); break; }
775 case ec_ctrlp_set: { set_controller_parameter(first_action_argument_as_float()); break; }
776
777 case ec_cop_register: { cop_register(); break; }
778 case ec_preset_register: { preset_register(); break; }
779 case ec_ladspa_register: { ladspa_register(); break; }
780 case ec_lv2_register: { lv2_register(); break; }
781 case ec_ctrl_register: { ctrl_register(); break; }
782
783 case ec_map_cop_list: { cop_descriptions(); break; }
784 case ec_map_preset_list: { preset_descriptions(); break; }
785 case ec_map_ladspa_list: { ladspa_descriptions(false); break; }
786 case ec_map_ladspa_id_list: { ladspa_descriptions(true); break; }
787 case ec_map_lv2_list: { lv2_descriptions(); break; }
788 case ec_map_ctrl_list: { ctrl_descriptions(); break; }
789
790 // ---
791 // Engine commands
792 // ---
793 case ec_engine_launch: {
794 if (is_engine_ready_for_commands() != true)
795 engine_start();
796 else
797 set_last_error("Engine already running, use 'engine-halt' first.");
798 break;
799 }
800 case ec_engine_halt: {
801 if (is_engine_ready_for_commands() == true)
802 close_engine();
803 else
804 set_last_error("Engine not running, use 'engine-launch' first.");
805 break;
806 }
807 case ec_engine_status: { set_last_string(engine_status()); break; }
808
809 // ---
810 // Internal commands
811 // ---
812 case ec_int_cmd_list: { set_last_string_list(registered_commands_list()); break; }
813 case ec_int_log_history: { set_last_string(ECA_LOGGER::instance().log_history()); break; }
814 case ec_int_output_mode_wellformed: {
815 ECA_LOGGER::attach_logger(new ECA_LOGGER_WELLFORMED());
816 wellformed_mode_rep = true;
817 break;
818 }
819 case ec_int_set_float_to_string_precision: { set_float_to_string_precision(first_action_argument_as_int()); break; }
820 case ec_int_set_log_history_length: { ECA_LOGGER::instance().set_log_history_length(first_action_argument_as_int()); break; }
821 case ec_int_version_string: { set_last_string(ecasound_library_version); break; }
822 case ec_int_version_lib_current: { set_last_integer(ecasound_library_version_current); break; }
823 case ec_int_version_lib_revision: { set_last_integer(ecasound_library_version_revision); break; }
824 case ec_int_version_lib_age: { set_last_integer(ecasound_library_version_age); break; }
825
826 // ---
827 // Dump commands
828 // ---
829 case ec_dump_target: { ctrl_dump_rep.set_dump_target(first_action_argument_as_string()); break; }
830 case ec_dump_status: { ctrl_dump_rep.dump_status(); break; }
831 case ec_dump_position: { ctrl_dump_rep.dump_position(); break; }
832 case ec_dump_length: { ctrl_dump_rep.dump_length(); break; }
833 case ec_dump_cs_status: { ctrl_dump_rep.dump_chainsetup_status(); break; }
834 case ec_dump_c_selected: { ctrl_dump_rep.dump_selected_chain(); break; }
835 case ec_dump_ai_selected: { ctrl_dump_rep.dump_selected_audio_input(); break; }
836 case ec_dump_ai_position: { ctrl_dump_rep.dump_audio_input_position(); break; }
837 case ec_dump_ai_length: { ctrl_dump_rep.dump_audio_input_length(); break; }
838 case ec_dump_ai_open_state: { ctrl_dump_rep.dump_audio_input_open_state(); break; }
839 case ec_dump_ao_selected: { ctrl_dump_rep.dump_selected_audio_output(); break; }
840 case ec_dump_ao_position: { ctrl_dump_rep.dump_audio_output_position(); break; }
841 case ec_dump_ao_length: { ctrl_dump_rep.dump_audio_output_length(); break; }
842 case ec_dump_ao_open_state: { ctrl_dump_rep.dump_audio_output_open_state(); break; }
843 case ec_dump_cop_value:
844 {
845 vector<string> temp = kvu_string_to_vector(first_action_argument_as_string(), ',');
846 if (temp.size() > 1) {
847 ctrl_dump_rep.dump_chain_operator_value(atoi(temp[0].c_str()),
848 atoi(temp[1].c_str()));
849 }
850 break;
851 }
852
853 // ---
854 // Commands with external dependencies
855 // ---
856 #if ECA_COMPILE_JACK
857 case ec_jack_connect:
858 {
859 const vector<string>& params = action_arguments_as_vector();
860 if (params.size() >= 2)
861 JACK_CONNECTIONS::connect(params[0].c_str(), params[1].c_str());
862 break;
863 }
864 case ec_jack_disconnect:
865 {
866 const vector<string>& params = action_arguments_as_vector();
867 if (params.size() >= 2)
868 JACK_CONNECTIONS::disconnect(params[0].c_str(), params[1].c_str());
869 break;
870 }
871 case ec_jack_list_connections:
872 {
873 string foo;
874 if (JACK_CONNECTIONS::list_connections(&foo) == true)
875 set_last_string(foo);
876 else
877 set_last_error("Unable to a list of JACK connections.");
878 break;
879 }
880 #endif
881
882 } // <-- switch-case
883
884
885 if (action_reconnect == true) {
886 if (is_selected() == false ||
887 is_valid() == false) {
888 set_last_error("Can't reconnect chainsetup.");
889 }
890 else {
891 connect_chainsetup(0);
892 if (selected_chainsetup() != connected_chainsetup()) {
893 set_last_error("Can't reconnect chainsetup.");
894 }
895 else {
896 if (action_restart == true) {
897 DBC_CHECK(is_running() != true);
898 start();
899 }
900 }
901 }
902 }
903 }
904
905 /**
906 * Executes chainsetup edit on connect chainsetup.
907 *
908 * @pre is_connected()
909 */
execute_edit_on_connected(const chainsetup_edit_t & edit)910 bool ECA_CONTROL::execute_edit_on_connected(const chainsetup_edit_t& edit)
911 {
912 DBC_REQUIRE(is_connected() == true);
913
914 bool retval = false;
915
916 if (is_engine_ready_for_commands() == true) {
917 ECA_ENGINE::complex_command_t engine_cmd;
918 engine_cmd.type = ECA_ENGINE::ep_exec_edit;
919 engine_cmd.cs = edit;
920 engine_repp->command(engine_cmd);
921 retval = true;
922 }
923 else {
924 /* note: engine not yet running, execute edit directly */
925 retval = session_repp->connected_chainsetup_repp->execute_edit(edit);
926 }
927
928 return retval;
929 }
930
931 /**
932 * Executes chainsetup edit on selected chainsetup.
933 *
934 * @param edit object specifying the edit action
935 * @param index if non-negative, override the chainsetup selection
936 */
execute_edit_on_selected(const chainsetup_edit_t & edit,int index)937 bool ECA_CONTROL::execute_edit_on_selected(const chainsetup_edit_t& edit, int index)
938 {
939 bool retval = false;
940
941 ECA_CHAINSETUP *csetup = 0;
942
943 if (index < 0) {
944 csetup = selected_chainsetup_repp;
945 }
946 else {
947 if (index >= 0 &&
948 index < static_cast<int>(session_repp->chainsetups_rep.size())) {
949 csetup = session_repp->chainsetups_rep[index];
950 }
951 }
952
953 /* note: make sure that if the selected chainsetup is
954 * in use by the engine, the edit is performed
955 * by the engine thread!
956 */
957 if (csetup != 0) {
958 if (csetup->is_enabled() == true &&
959 is_engine_ready_for_commands() == true) {
960 execute_edit_on_connected(edit);
961 }
962 else {
963 csetup->execute_edit(edit);
964 }
965 }
966
967 return retval;
968 }
969
print_last_value(struct eci_return_value * retval) const970 void ECA_CONTROL::print_last_value(struct eci_return_value *retval) const
971 {
972 std::string result;
973
974 if (retval->type == eci_return_value::retval_error) {
975 result += "ERROR: ";
976 }
977
978 result += ECA_CONTROL_MAIN::return_value_to_string(retval);
979
980 if (wellformed_mode_rep != true) {
981 if (result.size() > 0)
982 ECA_LOG_MSG(ECA_LOGGER::eiam_return_values, result);
983 }
984 else {
985 /* in wellformed-output-mode we always create return output */
986 ECA_LOG_MSG(ECA_LOGGER::eiam_return_values,
987 std::string(return_value_type_to_string(retval)) +
988 " " + result);
989 }
990 }
991
chainsetup_details_to_string(const ECA_CHAINSETUP * cs) const992 string ECA_CONTROL::chainsetup_details_to_string(const ECA_CHAINSETUP* cs) const
993 {
994 string result;
995 vector<CHAIN*>::const_iterator chain_citer;
996
997 result += "\n -> Objects..: " + kvu_numtostr(cs->inputs.size());
998 result += " inputs, " + kvu_numtostr(cs->outputs.size());
999 result += " outputs, " + kvu_numtostr(cs->chains.size());
1000 result += " chains";
1001
1002 // FIXME: add explanations on why the chainsetup cannot be
1003 // connected
1004
1005 result += "\n -> State....: ";
1006
1007 if (cs->is_locked()) {
1008 result += "connected to engine (engine status: ";
1009 result += engine_status() + ")";
1010 }
1011 else if (cs->is_enabled() && is_engine_created() == true) {
1012 result += "connected (engine status: ";
1013 result += engine_status() + ")";
1014 }
1015 else if (cs->is_enabled())
1016 result += "connected (engine not yet running)";
1017 else if (cs->is_valid())
1018 result += "valid (can be connected)";
1019 else
1020 result += "not valid (cannot be connected)";
1021
1022 result += "\n -> Position.: ";
1023 result += kvu_numtostr(cs->position_in_seconds_exact(), 3);
1024 result += " / ";
1025 if (cs->length_set())
1026 result += kvu_numtostr(cs->length_in_seconds_exact(), 3);
1027 else
1028 result += "inf";
1029
1030 result += "\n -> Options..: ";
1031 result += cs->options_to_string();
1032
1033 for(chain_citer = cs->chains.begin();
1034 chain_citer != cs->chains.end();) {
1035 result += "\n -> Chain \"" + (*chain_citer)->name() + "\": ";
1036 int idx =
1037 (*chain_citer)->connected_input();
1038 if (idx >= 0)
1039 result += ECA_OBJECT_FACTORY::audio_object_to_eos(cs->inputs[idx], "i");
1040 result += " ";
1041 result += (*chain_citer)->to_string();
1042 idx = (*chain_citer)->connected_output();
1043 if (idx >= 0)
1044 result += ECA_OBJECT_FACTORY::audio_object_to_eos(cs->outputs[idx], "o");
1045
1046 ++chain_citer;
1047 }
1048
1049 return result;
1050 }
1051
chainsetup_status(void) const1052 string ECA_CONTROL::chainsetup_status(void) const
1053 {
1054 vector<ECA_CHAINSETUP*>::const_iterator cs_citer = session_repp->chainsetups_rep.begin();
1055 int index = 0;
1056 string result ("### Chainsetup status ###\n");
1057
1058 while(cs_citer != session_repp->chainsetups_rep.end()) {
1059 result += "Chainsetup (" + kvu_numtostr(++index) + ") \"";
1060 result += (*cs_citer)->name() + "\" ";
1061
1062 if (*cs_citer ==
1063 selected_chainsetup_repp)
1064 result += "[selected] ";
1065 if (*cs_citer ==
1066 session_repp->connected_chainsetup_repp)
1067 result += "[connected] ";
1068
1069 if ((*cs_citer == selected_chainsetup_repp) ||
1070 (*cs_citer == session_repp->connected_chainsetup_repp))
1071 result += chainsetup_details_to_string((*cs_citer));
1072 else
1073 result += ": <detailed status omitted -- set as selected to see full status>";
1074
1075 ++cs_citer;
1076 if (cs_citer != session_repp->chainsetups_rep.end()) result += "\n";
1077 }
1078
1079 return result;
1080 }
1081
chain_status(void) const1082 string ECA_CONTROL::chain_status(void) const
1083 {
1084 // --------
1085 DBC_REQUIRE(is_selected() == true);
1086 // --------
1087
1088 MESSAGE_ITEM mitem;
1089 vector<CHAIN*>::const_iterator chain_citer;
1090 const vector<string>& schains = selected_chainsetup_repp->selected_chains();
1091 mitem << "### Chain status (chainsetup '"
1092 << selected_chainsetup()
1093 << "') ###\n";
1094
1095 for(chain_citer = selected_chainsetup_repp->chains.begin(); chain_citer != selected_chainsetup_repp->chains.end();) {
1096 mitem << "Chain \"" << (*chain_citer)->name() << "\" ";
1097 if ((*chain_citer)->is_muted()) mitem << "[muted] ";
1098 if ((*chain_citer)->is_bypassed()) mitem << "[bypassed] ";
1099 if (find(schains.begin(), schains.end(), (*chain_citer)->name()) != schains.end()) mitem << "[selected] ";
1100 for(int n = 0; n < (*chain_citer)->number_of_chain_operators(); n++) {
1101 mitem << "\"" << (*chain_citer)->get_chain_operator(n)->name() << "\"";
1102 if (n == (*chain_citer)->number_of_chain_operators()) mitem << " -> ";
1103 }
1104 ++chain_citer;
1105 if (chain_citer != selected_chainsetup_repp->chains.end()) mitem << "\n";
1106 }
1107
1108 return mitem.to_string();
1109 }
1110
chain_operator_status(void) const1111 string ECA_CONTROL::chain_operator_status(void) const
1112 {
1113 // --------
1114 DBC_REQUIRE(is_selected() == true);
1115 // --------
1116
1117 MESSAGE_ITEM msg;
1118 string st_info_string;
1119 vector<CHAIN*>::const_iterator chain_citer = selected_chainsetup_repp->chains.begin();
1120
1121 msg << "### Chain operator status (chainsetup '"
1122 << selected_chainsetup()
1123 << "') ###\n";
1124
1125 while(chain_citer != selected_chainsetup_repp->chains.end()) {
1126 msg << "Chain \"" << (*chain_citer)->name() << "\":\n";
1127 for(int p = 0; p < (*chain_citer)->number_of_chain_operators(); p++) {
1128 const CHAIN_OPERATOR* cop = (*chain_citer)->get_chain_operator(p);
1129 msg << "\t";
1130 msg << p + 1 << ". ";
1131 msg << cop->name();
1132 if ((*chain_citer)->is_operator_bypassed(p + 1))
1133 msg << " (BYPASSED)";
1134 for(int n = 0; n < cop->number_of_params(); n++) {
1135 if (n == 0) msg << ": ";
1136 msg << "[" << n + 1 << "] ";
1137 msg << cop->get_parameter_name(n + 1);
1138 msg << " ";
1139 msg << float_to_string(cop->get_parameter(n + 1));
1140 if (n + 1 < cop->number_of_params()) msg << ", ";
1141 }
1142 st_info_string = cop->status();
1143 if (st_info_string.empty() == false) {
1144 msg << "\n\tStatus info:\n" << st_info_string;
1145 }
1146 if (p + 1 < (*chain_citer)->number_of_chain_operators()) msg << "\n";
1147 }
1148 ++chain_citer;
1149 if (chain_citer != selected_chainsetup_repp->chains.end()) msg << "\n";
1150 }
1151 return msg.to_string();
1152 }
1153
controller_status(void) const1154 string ECA_CONTROL::controller_status(void) const
1155 {
1156 // --------
1157 DBC_REQUIRE(is_selected() == true);
1158 // --------
1159
1160 MESSAGE_ITEM mitem;
1161 string st_info_string;
1162 vector<CHAIN*>::const_iterator chain_citer;
1163
1164 mitem << "### Controller status (chainsetup '"
1165 << selected_chainsetup()
1166 << "') ###\n";
1167
1168 for(chain_citer = selected_chainsetup_repp->chains.begin(); chain_citer != selected_chainsetup_repp->chains.end();) {
1169 mitem << "Chain \"" << (*chain_citer)->name() << "\":\n";
1170 for(int p = 0; p < (*chain_citer)->number_of_controllers(); p++) {
1171 const GENERIC_CONTROLLER* gtrl = (*chain_citer)->get_controller(p);
1172 mitem << "\t" << p + 1 << ". " << gtrl->name() << ": ";
1173 for(int n = 0; n < gtrl->number_of_params(); n++) {
1174 mitem << "\n\t\t[" << n + 1 << "] ";
1175 mitem << gtrl->get_parameter_name(n + 1);
1176 mitem << " ";
1177 mitem << float_to_string(gtrl->get_parameter(n + 1));
1178 if (n + 1 < gtrl->number_of_params()) mitem << ", ";
1179 }
1180 st_info_string = gtrl->status();
1181 if (st_info_string.empty() == false) {
1182 mitem << "\n\t -- Status info: " << st_info_string;
1183 }
1184 if (p + 1 < (*chain_citer)->number_of_controllers()) mitem << "\n";
1185 }
1186 ++chain_citer;
1187 if (chain_citer != selected_chainsetup_repp->chains.end()) mitem << "\n";
1188 }
1189 return mitem.to_string();
1190 }
1191
aio_status(void) const1192 string ECA_CONTROL::aio_status(void) const
1193 {
1194 // --------
1195 DBC_REQUIRE(is_selected() == true);
1196 // --------
1197
1198 string st_info_string;
1199 vector<AUDIO_IO*>::size_type adev_sizet = 0;
1200 vector<AUDIO_IO*>::const_iterator adev_citer = selected_chainsetup_repp->inputs.begin();
1201
1202 st_info_string += "### Audio input/output status (chainsetup '" +
1203 selected_chainsetup() + "') ###\n";
1204
1205 while(adev_citer != selected_chainsetup_repp->inputs.end()) {
1206 st_info_string += "Input (" + kvu_numtostr(adev_sizet + 1) + "): \"";
1207 for(int n = 0; n < (*adev_citer)->number_of_params(); n++) {
1208 st_info_string += (*adev_citer)->get_parameter(n + 1);
1209 if (n + 1 < (*adev_citer)->number_of_params()) st_info_string += ",";
1210 }
1211 st_info_string += "\" - [" + (*adev_citer)->name() + "]";
1212 if ((*adev_citer) == selected_audio_input_repp) st_info_string += " [selected]";
1213 st_info_string += "\n -> connected to chains \"";
1214 vector<string> temp = selected_chainsetup_repp->get_attached_chains_to_input((selected_chainsetup_repp->inputs)[adev_sizet]);
1215 vector<string>::const_iterator p = temp.begin();
1216 while (p != temp.end()) {
1217 st_info_string += *p;
1218 ++p;
1219 if (p != temp.end()) st_info_string += ",";
1220 }
1221 st_info_string += "\": " + (*adev_citer)->status() + "\n";
1222 ++adev_sizet;
1223 ++adev_citer;
1224 }
1225
1226 adev_sizet = 0;
1227 adev_citer = selected_chainsetup_repp->outputs.begin();
1228 while(adev_citer != selected_chainsetup_repp->outputs.end()) {
1229 st_info_string += "Output (" + kvu_numtostr(adev_sizet + 1) + "): \"";
1230 for(int n = 0; n < (*adev_citer)->number_of_params(); n++) {
1231 st_info_string += (*adev_citer)->get_parameter(n + 1);
1232 if (n + 1 < (*adev_citer)->number_of_params()) st_info_string += ",";
1233 }
1234 st_info_string += "\" - [" + (*adev_citer)->name() + "]";
1235 if ((*adev_citer) == selected_audio_output_repp) st_info_string += " [selected]";
1236 st_info_string += "\n -> connected to chains \"";
1237 vector<string> temp = selected_chainsetup_repp->get_attached_chains_to_output((selected_chainsetup_repp->outputs)[adev_sizet]);
1238 vector<string>::const_iterator p = temp.begin();
1239 while (p != temp.end()) {
1240 st_info_string += *p;
1241 ++p;
1242 if (p != temp.end()) st_info_string += ",";
1243 }
1244 st_info_string += "\": ";
1245 st_info_string += (*adev_citer)->status();
1246 ++adev_sizet;
1247 ++adev_citer;
1248 if (adev_sizet < selected_chainsetup_repp->outputs.size()) st_info_string += "\n";
1249 }
1250 return st_info_string;
1251 }
1252
aio_register(void)1253 void ECA_CONTROL::aio_register(void)
1254 {
1255 ECA_LOG_MSG(ECA_LOGGER::info, "Registered audio object types:\n");
1256 string result (eca_aio_register_sub(ECA_OBJECT_FACTORY::audio_io_nonrt_map()));
1257
1258 result += "\n";
1259
1260 result += eca_aio_register_sub(ECA_OBJECT_FACTORY::audio_io_rt_map());
1261
1262 set_last_string(result);
1263 }
1264
eca_aio_register_sub(ECA_OBJECT_MAP & objmap)1265 static string eca_aio_register_sub(ECA_OBJECT_MAP& objmap)
1266 {
1267 string result;
1268 const list<string>& objlist = objmap.registered_objects();
1269 list<string>::const_iterator p = objlist.begin();
1270 int count = 1;
1271 while(p != objlist.end()) {
1272 string temp;
1273 const AUDIO_IO* q = dynamic_cast<const AUDIO_IO*>(objmap.object_expr(*p));
1274
1275 DBC_CHECK(q != 0);
1276
1277 if (q != 0) {
1278 int params = q->number_of_params();
1279 if (params > 0) {
1280 temp += ": ";
1281 for(int n = 0; n < params; n++) {
1282 temp += q->get_parameter_name(n + 1);
1283 if (n + 1 < params) temp += ",";
1284 }
1285 }
1286
1287 result += kvu_numtostr(count) + ". " + q->name() + ", regex: " +
1288 objmap.keyword_to_expr(*p) + ", params" + temp;
1289 result += "\n";
1290
1291 ++count;
1292 }
1293 // else std::cerr << "Failed obj: " << *p << "." << std::endl;
1294
1295 ++p;
1296 }
1297 return result;
1298 }
1299
cop_register(void)1300 void ECA_CONTROL::cop_register(void)
1301 {
1302 ECA_LOG_MSG(ECA_LOGGER::info, "Registered chain operators:\n");
1303 string result;
1304 const list<string>& objlist = ECA_OBJECT_FACTORY::chain_operator_map().registered_objects();
1305 list<string>::const_iterator p = objlist.begin();
1306 int count = 1;
1307 while(p != objlist.end()) {
1308 string temp;
1309 const CHAIN_OPERATOR* q = dynamic_cast<const CHAIN_OPERATOR*>(ECA_OBJECT_FACTORY::chain_operator_map().object(*p));
1310 if (q != 0) {
1311 int params = q->number_of_params();
1312 for(int n = 0; n < params; n++) {
1313 if (n == 0) temp += ":";
1314 temp += q->get_parameter_name(n + 1);
1315 if (n + 1 < params) temp += ",";
1316 }
1317 result += kvu_numtostr(count) + ". " + q->name() + ", -" + *p + temp;
1318 result += "\n";
1319 ++count;
1320 }
1321 ++p;
1322 }
1323 set_last_string(result);
1324 }
1325
preset_register(void)1326 void ECA_CONTROL::preset_register(void)
1327 {
1328 ECA_LOG_MSG(ECA_LOGGER::info, "Registered effect presets:\n");
1329 string result;
1330 #ifndef ECA_DISABLE_EFFECTS
1331 const list<string>& objlist = ECA_OBJECT_FACTORY::preset_map().registered_objects();
1332 list<string>::const_iterator p = objlist.begin();
1333 int count = 1;
1334 while(p != objlist.end()) {
1335 string temp;
1336 const PRESET* q = dynamic_cast<const PRESET*>(ECA_OBJECT_FACTORY::preset_map().object(*p));
1337 if (q != 0) {
1338 int params = q->number_of_params();
1339 for(int n = 0; n < params; n++) {
1340 if (n == 0) temp += ":";
1341 temp += q->get_parameter_name(n + 1);
1342 if (n + 1 < params) temp += ",";
1343 }
1344
1345 result += kvu_numtostr(count) + ". " + q->name() + ", -pn:" + *p + temp;
1346 result += "\n";
1347
1348 ++count;
1349 }
1350 ++p;
1351 }
1352 #endif
1353 set_last_string(result);
1354 }
1355
1356
ladspa_register(void)1357 void ECA_CONTROL::ladspa_register(void)
1358 {
1359 ECA_LOG_MSG(ECA_LOGGER::info, "Registered LADSPA plugins:\n");
1360 string result;
1361 #ifndef ECA_DISABLE_EFFECTS
1362 const list<string>& objlist = ECA_OBJECT_FACTORY::ladspa_plugin_map().registered_objects();
1363 list<string>::const_iterator p = objlist.begin();
1364 int count = 1;
1365 while(p != objlist.end()) {
1366 const EFFECT_LADSPA* q = dynamic_cast<const EFFECT_LADSPA*>(ECA_OBJECT_FACTORY::ladspa_plugin_map().object(*p));
1367 if (q != 0) {
1368 string temp = "\n\t-el:" + q->unique() + ",";
1369 int params = q->number_of_params();
1370 for(int n = 0; n < params; n++) {
1371 temp += "'" + q->get_parameter_name(n + 1) + "'";
1372 if (n + 1 < params) temp += ",";
1373 }
1374
1375 result += kvu_numtostr(count) + ". " + q->name() + "" + temp;
1376 result += "\n";
1377
1378 ++count;
1379 }
1380 ++p;
1381 }
1382 #endif
1383 set_last_string(result);
1384 }
1385
lv2_register(void)1386 void ECA_CONTROL::lv2_register(void)
1387 {
1388 ECA_LOG_MSG(ECA_LOGGER::info, "Registered LV2 plugins:\n");
1389 string result;
1390 #if !defined(ECA_DISABLE_EFFECTS) && defined(ECA_USE_LIBLILV)
1391 const list<string>& objlist = ECA_OBJECT_FACTORY::lv2_plugin_map().registered_objects();
1392 list<string>::const_iterator p = objlist.begin();
1393 int count = 1;
1394 while(p != objlist.end()) {
1395 const EFFECT_LV2* q = dynamic_cast<const EFFECT_LV2*>(ECA_OBJECT_FACTORY::lv2_plugin_map().object(*p));
1396 if (q != 0) {
1397 string temp = "\n\t-elv2:" + q->unique() + ",";
1398 int params = q->number_of_params();
1399 for(int n = 0; n < params; n++) {
1400 temp += "'" + q->get_parameter_name(n + 1) + "'";
1401 if (n + 1 < params) temp += ",";
1402 }
1403
1404 result += kvu_numtostr(count) + ". " + q->name() + "" + temp;
1405 result += "\n";
1406
1407 ++count;
1408 }
1409 ++p;
1410 }
1411 #endif
1412 set_last_string(result);
1413 }
1414
1415
ctrl_register(void)1416 void ECA_CONTROL::ctrl_register(void)
1417 {
1418 ECA_LOG_MSG(ECA_LOGGER::info, "Registered controllers:\n");
1419 string result;
1420 const list<string>& objlist = ECA_OBJECT_FACTORY::controller_map().registered_objects();
1421 list<string>::const_iterator p = objlist.begin();
1422 int count = 1;
1423 while(p != objlist.end()) {
1424 string temp;
1425 const GENERIC_CONTROLLER* q = dynamic_cast<const GENERIC_CONTROLLER*>(ECA_OBJECT_FACTORY::controller_map().object(*p));
1426 if (q != 0) {
1427 int params = q->number_of_params();
1428 for(int n = 0; n < params; n++) {
1429 if (n == 0) temp += ":";
1430 temp += q->get_parameter_name(n + 1);
1431 if (n + 1 < params) temp += ",";
1432 }
1433
1434 result += kvu_numtostr(count) + ". " + q->name() + ", -" + *p +
1435 temp;
1436 result += "\n";
1437
1438 ++count;
1439 }
1440 ++p;
1441 }
1442 set_last_string(result);
1443 }
1444
1445 /**
1446 * Print description of all chain operators and
1447 * their parameters.
1448 */
operator_descriptions_helper(const ECA_OBJECT_MAP & arg,string * result)1449 void ECA_CONTROL::operator_descriptions_helper(const ECA_OBJECT_MAP& arg, string* result)
1450 {
1451 /* switch to "C" locale to avoid strange floating point
1452 * presentations that could break the output format
1453 * (for example "a,b" insteof of "a.b" */
1454 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
1455 string old_locale (setlocale(LC_ALL, "C"));
1456 #endif
1457
1458 const list<string>& objlist = arg.registered_objects();
1459 list<string>::const_iterator p = objlist.begin();
1460 int count = 1;
1461 while(p != objlist.end()) {
1462 string temp;
1463 const OPERATOR* q = dynamic_cast<const OPERATOR*>(arg.object(*p));
1464 if (q != 0) {
1465 /* FIXME: prefer backslash escaped over '_' to handle commas */
1466
1467 /* 1. keyword */
1468 *result += kvu_string_search_and_replace(*p, ',', '_');
1469 /* 2. name */
1470 *result += "," + kvu_string_search_and_replace(q->name(), ',', '_');
1471 /* 3. description */
1472 *result += "," + kvu_string_search_and_replace(q->description(), ',', '_');
1473
1474 int params = q->number_of_params();
1475
1476 /* 4. number of params */
1477 *result += "," + kvu_numtostr(params);
1478
1479 /* 5. description of params (for all params) */
1480 for(int n = 0; n < params; n++) {
1481 struct OPERATOR::PARAM_DESCRIPTION pd;
1482 q->parameter_description(n + 1, &pd);
1483
1484 /* 5.1 name of param */
1485 *result += "," + kvu_string_search_and_replace(q->get_parameter_name(n + 1), ',', '_');
1486 /* 5.2 description */
1487 *result += "," + kvu_string_search_and_replace(pd.description, ',', '_');
1488 /* 5.3 default value */
1489 *result += "," + float_to_string(pd.default_value);
1490 /* 5.4 is bounded above (1=yes, 0=no) */
1491 *result += ",above=" + kvu_numtostr(static_cast<int>(pd.bounded_above));
1492 /* 5.5 upper bound */
1493 *result += ",upper=" + float_to_string(pd.upper_bound);
1494 /* 5.6 is bounded below (1=yes, 0=no) */
1495 *result += ",below=" + kvu_numtostr(static_cast<int>(pd.bounded_below));
1496 /* 5.7 lower bound */
1497 *result += ",lower=" + float_to_string(pd.lower_bound);
1498 /* 5.8. is toggled (1=yes, 0=no) */
1499 *result += "," + kvu_numtostr(static_cast<int>(pd.toggled));
1500 /* 5.9. is integer value (1=yes, 0=no) */
1501 *result += "," + kvu_numtostr(static_cast<int>(pd.integer));
1502 /* 5.10. is logarithmis value (1=yes, 0=no) */
1503 *result += "," + kvu_numtostr(static_cast<int>(pd.logarithmic));
1504 /* 5.11. is output value (1=yes, 0=no) */
1505 *result += ",output=" + kvu_numtostr(static_cast<int>(pd.output));
1506 }
1507 *result += "\n";
1508 ++count;
1509 }
1510 ++p;
1511 }
1512
1513 /* see above */
1514 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
1515 setlocale(LC_ALL, old_locale.c_str());
1516 #endif
1517 }
1518
1519 /**
1520 * Print the description of all chain operators and
1521 * their parameters.
1522 */
cop_descriptions(void)1523 void ECA_CONTROL::cop_descriptions(void)
1524 {
1525 string result;
1526 operator_descriptions_helper(ECA_OBJECT_FACTORY::chain_operator_map(), &result);
1527 set_last_string(result);
1528 }
1529
1530 /**
1531 * Prints the description of all effect presets and
1532 * their parameters.
1533 */
preset_descriptions(void)1534 void ECA_CONTROL::preset_descriptions(void)
1535 {
1536 string result;
1537 operator_descriptions_helper(ECA_OBJECT_FACTORY::preset_map(), &result);
1538 set_last_string(result);
1539 }
1540
1541 /**
1542 * Prints the description of all LADSPA plugins and
1543 * their parameters.
1544 */
ladspa_descriptions(bool use_id)1545 void ECA_CONTROL::ladspa_descriptions(bool use_id)
1546 {
1547 string result;
1548 if (use_id) {
1549 operator_descriptions_helper(ECA_OBJECT_FACTORY::ladspa_plugin_id_map(), &result);
1550 }
1551 else {
1552 operator_descriptions_helper(ECA_OBJECT_FACTORY::ladspa_plugin_map(), &result);
1553 }
1554 set_last_string(result);
1555 }
1556
1557 /**
1558 * Prints the description of all LV2 plugins and
1559 * their parameters.
1560 */
lv2_descriptions()1561 void ECA_CONTROL::lv2_descriptions()
1562 {
1563 string result;
1564 operator_descriptions_helper(ECA_OBJECT_FACTORY::lv2_plugin_map(), &result);
1565 set_last_string(result);
1566 }
1567
1568 /**
1569 * Print the description of all controllers and
1570 * their parameters.
1571 */
ctrl_descriptions(void)1572 void ECA_CONTROL::ctrl_descriptions(void)
1573 {
1574 string result;
1575 operator_descriptions_helper(ECA_OBJECT_FACTORY::controller_map(), &result);
1576 set_last_string(result);
1577 }
1578