1
// ------------------------------------------------------------------------
2
// eca-chainsetup.cpp: Class representing an ecasound chainsetup object.
3
// Copyright (C) 1999-2006,2008,2009,2011 Kai Vehmanen
4
// Copyright (C) 2005 Stuart Allie
7
// eca-style-version: 3 (see Ecasound Programmer's Guide)
9
// This program is free software; you can redistribute it and/or modify
10
// it under the terms of the GNU General Public License as published by
11
// the Free Software Foundation; either version 2 of the License, or
12
// (at your option) any later version.
14
// This program is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
// GNU General Public License for more details.
19
// You should have received a copy of the GNU General Public License
20
// along with this program; if not, write to the Free Software
21
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
// ------------------------------------------------------------------------
30
#include <algorithm> /* find() */
36
#include <sys/types.h> /* POSIX: getpid() */
37
#include <unistd.h> /* POSIX: getpid() */
38
#ifdef HAVE_SYS_MMAN_H
39
#include <sys/mman.h> /* POSIX: for mlockall() */
42
#ifdef ECA_COMPILE_JACK
43
#include <jack/jack.h>
47
#include <kvu_message_item.h>
48
#include <kvu_numtostr.h>
49
#include <kvu_rtcaps.h>
50
#include <kvu_utils.h>
52
#include "eca-resources.h"
53
#include "eca-session.h"
55
#include "generic-controller.h"
56
#include "eca-chainop.h"
57
#include "eca-chain.h"
60
#include "audioio-manager.h"
61
#include "audioio-device.h"
62
#include "audioio-buffered.h"
63
#include "audioio-loop.h"
64
#include "audioio-null.h"
65
#include "audioio-resample.h"
67
#include "eca-engine-driver.h"
68
#include "eca-object-factory.h"
69
#include "eca-object-map.h"
72
#include "midi-client.h"
74
#include "eca-object-factory.h"
75
#include "eca-chainsetup-position.h"
76
#include "sample-specs.h"
78
#include "eca-error.h"
79
#include "eca-logger.h"
81
#include "eca-chainsetup.h"
82
#include "eca-chainsetup_impl.h"
88
const string ECA_CHAINSETUP::default_audio_format_const = "s16_le,2,44100,i";
89
const string ECA_CHAINSETUP::default_bmode_nonrt_const = "1024,false,50,false,100000,true";
90
const string ECA_CHAINSETUP::default_bmode_rt_const = "1024,true,50,true,100000,true";
91
const string ECA_CHAINSETUP::default_bmode_rtlowlatency_const = "256,true,50,true,100000,false";
93
static void priv_erase_object(std::vector<AUDIO_IO*>* vec, const AUDIO_IO* obj);
96
* Construct from a vector of options.
98
* If any invalid options are passed us argument,
99
* interpret_result() will be 'false', and
100
* interpret_result_verbose() contains more detailed
103
ECA_CHAINSETUP::ECA_CHAINSETUP(const vector<string>& opts)
105
is_enabled_rep(false)
107
impl_repp = new ECA_CHAINSETUP_impl;
109
// FIXME: set default audio format here!
111
setup_name_rep = "untitled-chainsetup";
112
setup_filename_rep = "";
116
vector<string> options (opts);
117
cparser_rep.preprocess_options(options);
118
interpret_options(options);
119
if (interpret_result() == true) {
120
/* do not add default if there were parsing errors as
121
* it might hide real problems */
122
add_default_output();
123
add_default_midi_device();
126
ECA_LOG_MSG(ECA_LOGGER::info, "Chainsetup \"" + setup_name_rep + "\"");
130
* Constructs an empty chainsetup.
132
* @post buffersize != 0
134
ECA_CHAINSETUP::ECA_CHAINSETUP(void)
136
is_enabled_rep(false)
138
impl_repp = new ECA_CHAINSETUP_impl;
143
ECA_LOG_MSG(ECA_LOGGER::info, "Chainsetup created (empty)");
147
* Construct from a chainsetup file.
149
* If any invalid options are passed us argument,
150
* interpret_result() will be 'false', and
151
* interpret_result_verbose() contains more detailed
154
* @post buffersize != 0
156
ECA_CHAINSETUP::ECA_CHAINSETUP(const string& setup_file)
158
is_enabled_rep(false)
160
impl_repp = new ECA_CHAINSETUP_impl;
164
vector<string> options;
165
load_from_file(setup_file, options);
166
set_filename(setup_file);
167
if (name() == "") set_name(setup_file);
168
cparser_rep.preprocess_options(options);
169
interpret_options(options);
170
if (interpret_result() == true) {
171
/* do not add default if there were parsing errors as
172
* it might hide real problems */
173
add_default_output();
176
ECA_LOG_MSG(ECA_LOGGER::info,
178
+ name() + "\" created (file: "
185
ECA_CHAINSETUP::~ECA_CHAINSETUP(void)
187
ECA_LOG_MSG(ECA_LOGGER::system_objects,"ECA_CHAINSETUP destructor-in");
189
DBC_CHECK(is_locked() != true);
190
if (is_enabled() == true) {
193
DBC_CHECK(is_enabled() != true);
195
/* delete chain objects */
196
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
197
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Deleting chain \"" + (*q)->name() + "\".");
202
/* delete input db objects; reset all pointers to null */
203
for(vector<AUDIO_IO*>::iterator q = inputs.begin(); q != inputs.end(); q++) {
204
if (dynamic_cast<AUDIO_IO_DB_CLIENT*>(*q) != 0) {
205
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Deleting audio db-client \"" + (*q)->label() + "\".");
211
/* delete all actual audio input objects except loop devices; reset all pointers to null */
212
for(vector<AUDIO_IO*>::iterator q = inputs_direct_rep.begin(); q != inputs_direct_rep.end(); q++) {
213
if (dynamic_cast<LOOP_DEVICE*>(*q) == 0) {
214
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Deleting audio object \"" + (*q)->label() + "\".");
220
/* delete output db objects; reset all pointers to null */
221
for(vector<AUDIO_IO*>::iterator q = outputs.begin(); q != outputs.end(); q++) {
222
if (dynamic_cast<AUDIO_IO_DB_CLIENT*>(*q) != 0) {
223
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Deleting audio db-client \"" + (*q)->label() + "\".");
229
/* delete all actual audio output objects except loop devices; reset all pointers to null */
230
for(vector<AUDIO_IO*>::iterator q = outputs_direct_rep.begin(); q != outputs_direct_rep.end(); q++) {
231
// trouble with dynamic_cast with libecasoundc apps like ecalength?
232
if (dynamic_cast<LOOP_DEVICE*>(*q) == 0) {
233
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Deleting audio object \"" + (*q)->label() + "\".");
239
/* delete loop objects */
240
for(map<string,LOOP_DEVICE*>::iterator q = loop_map.begin(); q != loop_map.end(); q++) {
241
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Deleting loop device \"" + q->second->label() + "\".");
246
/* delete aio manager objects */
247
for(vector<AUDIO_IO_MANAGER*>::iterator q = aio_managers_rep.begin(); q != aio_managers_rep.end(); q++) {
248
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Deleting audio manager \"" + (*q)->name() + "\".");
255
ECA_LOG_MSG(ECA_LOGGER::system_objects,"ECA_CHAINSETUP destructor-out");
259
* Sets default values.
261
* @pre is_enabled() != true
263
void ECA_CHAINSETUP::set_defaults(void)
266
DBC_REQUIRE(is_enabled() != true);
269
/* note: defaults are set as specified in ecasoundrc(5) */
271
precise_sample_rates_rep = false;
272
ignore_xruns_rep = true;
274
pserver_repp = &impl_repp->pserver_rep;
275
midi_server_repp = &impl_repp->midi_server_rep;
276
engine_driver_repp = 0;
278
if (kvu_check_for_sched_fifo() == true) {
280
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Rtcaps detected.");
286
multitrack_mode_rep = false;
287
multitrack_mode_override_rep = false;
288
memory_locked_rep = false;
289
midi_server_needed_rep = false;
290
is_locked_rep = false;
291
selected_chain_index_rep = 0;
292
selected_ctrl_index_rep = 0;
293
selected_ctrl_param_index_rep = 0;
294
multitrack_mode_offset_rep = -1;
296
buffering_mode_rep = cs_bmode_auto;
297
active_buffering_mode_rep = cs_bmode_none;
299
set_output_openmode(AUDIO_IO::io_readwrite);
301
ECA_RESOURCES ecaresources;
302
if (ecaresources.has_any() != true) {
303
ECA_LOG_MSG(ECA_LOGGER::info,
304
"WARNING: Unable to read global resources. May result in incorrect behaviour.");
307
set_default_midi_device(ecaresources.resource("midi-device"));
308
string rc_temp = set_resource_helper(ecaresources,
309
"default-audio-format",
310
ECA_CHAINSETUP::default_audio_format_const);
311
cparser_rep.interpret_object_option("-f:" + rc_temp);
312
set_samples_per_second(default_audio_format().samples_per_second());
313
toggle_precise_sample_rates(ecaresources.boolean_resource("default-to-precise-sample-rates"));
314
rc_temp = set_resource_helper(ecaresources,
317
cparser_rep.interpret_object_option("-z:mixmode," + rc_temp);
319
impl_repp->bmode_nonrt_rep.set_all(set_resource_helper(ecaresources,
320
"bmode-defaults-nonrt",
321
ECA_CHAINSETUP::default_bmode_nonrt_const));
322
impl_repp->bmode_rt_rep.set_all(set_resource_helper(ecaresources,
324
ECA_CHAINSETUP::default_bmode_rt_const));
325
impl_repp->bmode_rtlowlatency_rep.set_all(set_resource_helper(ecaresources,
326
"bmode-defaults-rtlowlatency",
327
ECA_CHAINSETUP::default_bmode_rtlowlatency_const));
329
impl_repp->bmode_active_rep = impl_repp->bmode_nonrt_rep;
333
* Sets a resource value.
335
* Only used by ECA_CHAINSETUP::set_defaults.
337
string ECA_CHAINSETUP::set_resource_helper(const ECA_RESOURCES& ecaresources, const string& tag, const string& alternative)
339
if (ecaresources.has(tag) == true) {
340
return ecaresources.resource(tag);
343
ECA_LOG_MSG(ECA_LOGGER::system_objects,
344
"Using hardcoded defaults for \"" +
351
* Tests whether chainsetup is in a valid state.
353
bool ECA_CHAINSETUP::is_valid(void) const
355
return is_valid_for_connection(false);
359
* Checks whether chainsetup is valid for enabling/connecting.
360
* If chainsetup is not valid and 'verbose' is true, detected
361
* errors are reported via the logging subsystem.
363
bool ECA_CHAINSETUP::is_valid_for_connection(bool verbose) const
367
if (inputs.size() == 0) {
368
if (verbose) ECA_LOG_MSG(ECA_LOGGER::info,
369
"Unable to connect: No inputs in the current chainsetup. (1.1-NO-INPUTS)");
372
else if (outputs.size() == 0) {
373
if (verbose) ECA_LOG_MSG(ECA_LOGGER::info,
374
"Unable to connect: No outputs in the current chainsetup. (1.2-NO-OUTPUTS)");
377
else if (chains.size() == 0) {
378
if (verbose) ECA_LOG_MSG(ECA_LOGGER::info,
379
"Unable to connect: No chains in the current chainsetup. (1.3-NO-CHAINS)");
383
list<int> conn_inputs, conn_outputs;
385
for(vector<CHAIN*>::const_iterator q = chains.begin(); q != chains.end(); q++) {
386
/* log messages printed in CHAIN::is_valid() */
388
int id = (*q)->connected_input();
390
conn_inputs.push_back(id);
392
if ((*q)->is_valid() == false) {
394
if (verbose) ECA_LOG_MSG(ECA_LOGGER::info,
395
"Unable to connect: Chain \"" + (*q)->name() +
396
"\" is not valid. Following errors were detected:");
397
if (verbose && id == -1) {
398
ECA_LOG_MSG(ECA_LOGGER::info,
399
"Chain \"" + (*q)->name() + "\" is not connected to any input. "
400
"All chains must have exactly one valid input. (2.1-NO-CHAIN-INPUT)");
404
id = (*q)->connected_output();
406
conn_outputs.push_back(id);
408
if (verbose && (*q)->is_valid() == false) {
410
ECA_LOG_MSG(ECA_LOGGER::info,
411
"Chain \"" + (*q)->name() + "\" is not connected to any output. "
412
"All chains must have exactly one valid output. (2.2-NO-CHAIN-OUTPUT)");
417
// FIXME: doesn't work yet
420
for(int n = 0; n < static_cast<int>(inputs.size()); n++) {
421
if (std::find(conn_inputs.begin(), conn_inputs.end(), n) == conn_inputs.end()) {
422
ECA_LOG_MSG(ECA_LOGGER::info,
423
"WARNING: Input \"" + inputs[n]->label() + "\" is not connected to any chain. (3.1-DISCON-INPUT)");
427
for(int n = 0; n < static_cast<int>(outputs.size()); n++) {
428
if (std::find(conn_outputs.begin(), conn_outputs.end(), n) == conn_outputs.end()) {
429
ECA_LOG_MSG(ECA_LOGGER::info,
430
"WARNING: Output \"" + outputs[n]->label() + "\" is not connected to any chain. (3.2-DISCON-OUTPUT)");
434
} /* (verbose == true) */
439
void ECA_CHAINSETUP::set_buffering_mode(Buffering_mode_t value)
441
if (value == ECA_CHAINSETUP::cs_bmode_none)
442
buffering_mode_rep = ECA_CHAINSETUP::cs_bmode_auto;
444
buffering_mode_rep = value;
448
* Sets audio i/o manager option for manager
449
* object type 'mgrname' to be 'optionstr'.
450
* Previously set option string is overwritten.
452
void ECA_CHAINSETUP::set_audio_io_manager_option(const string& mgrname, const string& optionstr)
454
ECA_LOG_MSG(ECA_LOGGER::system_objects,
456
mgrname + "\" option string to \"" +
459
aio_manager_option_map_rep[mgrname] = optionstr;
460
propagate_audio_io_manager_options();
464
* Determinates the active buffering parameters based on
465
* defaults, user overrides and analyzing the current
466
* chainsetup configuration. If the resulting parameters
467
* are different from current ones, a state change is
470
void ECA_CHAINSETUP::select_active_buffering_mode(void)
472
if (buffering_mode() == ECA_CHAINSETUP::cs_bmode_none) {
473
active_buffering_mode_rep = ECA_CHAINSETUP::cs_bmode_auto;
476
if (!(multitrack_mode_override_rep == true &&
477
multitrack_mode_rep != true) &&
478
((multitrack_mode_override_rep == true &&
479
multitrack_mode_rep == true) ||
480
(number_of_realtime_inputs() > 0 &&
481
number_of_realtime_outputs() > 0 &&
482
number_of_non_realtime_inputs() > 0 &&
483
number_of_non_realtime_outputs() > 0 &&
484
chains.size() > 1))) {
485
ECA_LOG_MSG(ECA_LOGGER::info, "Multitrack-mode enabled.");
486
multitrack_mode_rep = true;
489
multitrack_mode_rep = false;
491
if (buffering_mode() == ECA_CHAINSETUP::cs_bmode_auto) {
493
/* initialize to 'nonrt', mt-disabled */
494
active_buffering_mode_rep = ECA_CHAINSETUP::cs_bmode_nonrt;
496
if (has_realtime_objects() == true) {
497
/* case 1: a multitrack setup */
498
if (multitrack_mode_rep == true) {
499
active_buffering_mode_rep = ECA_CHAINSETUP::cs_bmode_rt;
500
ECA_LOG_MSG(ECA_LOGGER::system_objects, "bmode-selection case-1");
503
/* case 2: rt-objects without priviledges for rt-scheduling */
504
else if (rtcaps_rep != true) {
505
ECA_LOG_MSG(ECA_LOGGER::info,
506
"NOTE: Real-time configuration, but insufficient privileges to utilize real-time scheduling (SCHED_FIFO). With small buffersizes, this may cause audible glitches during processing.");
507
toggle_raised_priority(false);
508
active_buffering_mode_rep = ECA_CHAINSETUP::cs_bmode_rt;
509
ECA_LOG_MSG(ECA_LOGGER::system_objects, "bmode-selection case-2");
512
/* case 3: no chain operators and "one-way rt-operation" */
513
else if (number_of_chain_operators() == 0 &&
514
(number_of_realtime_inputs() == 0 ||
515
number_of_realtime_outputs() == 0)) {
516
active_buffering_mode_rep = ECA_CHAINSETUP::cs_bmode_rt;
517
ECA_LOG_MSG(ECA_LOGGER::system_objects, "bmode-selection case-3");
520
/* case 4: default for rt-setups */
522
active_buffering_mode_rep = ECA_CHAINSETUP::cs_bmode_rtlowlatency;
523
ECA_LOG_MSG(ECA_LOGGER::system_objects, "bmode-selection case-4");
527
/* case 5: no rt-objects */
528
active_buffering_mode_rep = ECA_CHAINSETUP::cs_bmode_nonrt;
529
ECA_LOG_MSG(ECA_LOGGER::system_objects, "bmode-selection case-5");
533
/* user has explicitly selected the buffering mode */
534
active_buffering_mode_rep = buffering_mode();
535
ECA_LOG_MSG(ECA_LOGGER::system_objects, "bmode-selection explicit");
538
switch(active_buffering_mode_rep)
540
case ECA_CHAINSETUP::cs_bmode_nonrt: {
541
impl_repp->bmode_active_rep = impl_repp->bmode_nonrt_rep;
542
ECA_LOG_MSG(ECA_LOGGER::info,
543
"\"nonrt\" buffering mode selected.");
546
case ECA_CHAINSETUP::cs_bmode_rt: {
547
impl_repp->bmode_active_rep = impl_repp->bmode_rt_rep;
548
ECA_LOG_MSG(ECA_LOGGER::info,
549
"\"rt\" buffering mode selected.");
552
case ECA_CHAINSETUP::cs_bmode_rtlowlatency: {
553
impl_repp->bmode_active_rep = impl_repp->bmode_rtlowlatency_rep;
554
ECA_LOG_MSG(ECA_LOGGER::info,
555
"\"rtlowlatency\" buffering mode selected.");
558
default: { /* error! */ }
561
ECA_LOG_MSG(ECA_LOGGER::system_objects,
562
"Set buffering parameters to: \n--cut--" +
563
impl_repp->bmode_active_rep.to_string() +"\n--cut--");
567
* Enable chosen active buffering mode.
569
* Called only from enable().
571
void ECA_CHAINSETUP::enable_active_buffering_mode(void)
573
/* 1. if requested, lock all memory */
574
if (raised_priority() == true) {
581
/* 2. if necessary, switch between different db and direct modes */
582
if (double_buffering() == true) {
583
if (has_realtime_objects() != true) {
584
ECA_LOG_MSG(ECA_LOGGER::system_objects,
585
"No realtime objects; switching to direct mode.");
586
switch_to_direct_mode();
587
impl_repp->bmode_active_rep.toggle_double_buffering(false);
589
else if (has_nonrealtime_objects() != true) {
590
ECA_LOG_MSG(ECA_LOGGER::system_objects,
591
"Only realtime objects; switching to direct mode.");
592
switch_to_direct_mode();
593
impl_repp->bmode_active_rep.toggle_double_buffering(false);
595
else if (db_clients_rep == 0) {
596
ECA_LOG_MSG(ECA_LOGGER::system_objects,
597
"Switching to db mode.");
601
if (buffersize() != 0) {
602
impl_repp->pserver_rep.set_buffer_defaults(double_buffer_size() / buffersize(),
606
ECA_LOG_MSG(ECA_LOGGER::info,
607
"WARNING: Buffersize set to 0.");
608
impl_repp->pserver_rep.set_buffer_defaults(0, 0);
612
/* double_buffering() != true */
613
if (db_clients_rep > 0) {
614
ECA_LOG_MSG(ECA_LOGGER::system_objects,
615
"Switching to direct mode.");
616
switch_to_direct_mode();
620
/* 3. propagate buffersize value to all dependent objects */
621
/* FIXME: create a system for tracking buffesize aware objs */
624
void ECA_CHAINSETUP::switch_to_direct_mode(void)
626
switch_to_direct_mode_helper(&inputs, inputs_direct_rep);
627
switch_to_direct_mode_helper(&outputs, outputs_direct_rep);
629
DBC_ENSURE(db_clients_rep == 0);
633
void ECA_CHAINSETUP::switch_to_direct_mode_helper(vector<AUDIO_IO*>* objs,
634
const vector<AUDIO_IO*>& directobjs)
637
DBC_CHECK(objs->size() == directobjs.size());
640
for(size_t n = 0; n < objs->size(); n++) {
641
AUDIO_IO_DB_CLIENT* pobj = dynamic_cast<AUDIO_IO_DB_CLIENT*>((*objs)[n]);
644
(*objs)[n] = directobjs[n];
650
void ECA_CHAINSETUP::switch_to_db_mode(void)
652
switch_to_db_mode_helper(&inputs, inputs_direct_rep);
653
switch_to_db_mode_helper(&outputs, outputs_direct_rep);
656
void ECA_CHAINSETUP::switch_to_db_mode_helper(vector<AUDIO_IO*>* objs,
657
const vector<AUDIO_IO*>& directobjs)
660
DBC_REQUIRE(db_clients_rep == 0);
661
DBC_CHECK(objs->size() == directobjs.size());
664
for(size_t n = 0; n < directobjs.size(); n++) {
665
(*objs)[n] = add_audio_object_helper(directobjs[n]);
670
* Locks all memory with mlockall().
672
void ECA_CHAINSETUP::lock_all_memory(void)
675
if (::mlockall (MCL_CURRENT|MCL_FUTURE)) {
676
ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: Couldn't lock all memory!");
679
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Memory locked!");
680
memory_locked_rep = true;
683
ECA_LOG_MSG(ECA_LOGGER::info, "Memory locking not available.");
688
* Unlocks all memory with munlockall().
690
void ECA_CHAINSETUP::unlock_all_memory(void)
692
#ifdef HAVE_MUNLOCKALL
693
if (memory_locked_rep == true) {
694
if (::munlockall()) {
695
ECA_LOG_MSG(ECA_LOGGER::system_objects, "WARNING: Couldn't unlock all memory!");
698
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Memory unlocked!");
699
memory_locked_rep = false;
702
memory_locked_rep = false;
703
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Memory unlocking not available.");
708
* Adds a "default" chain to this chainsetup.
710
* @pre buffersize >= 0 && chains.size() == 0
711
* @pre is_locked() != true
713
* @post chains.back()->name() == "default" &&
714
* @post active_chainids.back() == "default"
716
void ECA_CHAINSETUP::add_default_chain(void)
719
DBC_REQUIRE(buffersize() >= 0);
720
DBC_REQUIRE(chains.size() == 0);
721
DBC_REQUIRE(is_locked() != true);
724
add_chain_helper("default");
725
selected_chainids.push_back("default");
728
DBC_ENSURE(chains.back()->name() == "default");
729
DBC_ENSURE(selected_chainids.back() == "default");
734
* Adds new chains to this chainsetup.
736
* @pre is_enabled() != true
738
void ECA_CHAINSETUP::add_new_chains(const vector<string>& newchains)
741
DBC_REQUIRE(is_enabled() != true);
744
for(vector<string>::const_iterator p = newchains.begin(); p != newchains.end(); p++) {
746
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
747
if (*p == (*q)->name()) exists = true;
749
if (exists == false) {
750
add_chain_helper(*p);
755
void ECA_CHAINSETUP::add_chain_helper(const string& name)
757
chains.push_back(new CHAIN());
758
chains.back()->name(name);
759
chains.back()->set_samples_per_second(samples_per_second());
760
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Chain \"" + name + "\" created.");
764
* Removes all selected chains from this chainsetup.
766
* @pre is_enabled() != true
768
void ECA_CHAINSETUP::remove_chains(void)
771
DBC_REQUIRE(is_enabled() != true);
772
DBC_DECLARE(size_t old_chains_size = chains.size());
773
DBC_DECLARE(size_t sel_chains_size = selected_chainids.size());
776
for(vector<string>::const_iterator a = selected_chainids.begin(); a != selected_chainids.end(); a++) {
777
vector<CHAIN*>::iterator q = chains.begin();
778
while(q != chains.end()) {
779
if (*a == (*q)->name()) {
787
selected_chainids.resize(0);
790
DBC_ENSURE(chains.size() == old_chains_size - sel_chains_size);
795
* Clears all selected chains. Removes all chain operators
798
* @pre is_locked() != true
800
void ECA_CHAINSETUP::clear_chains(void)
803
DBC_REQUIRE(is_locked() != true);
806
for(vector<string>::const_iterator a = selected_chainids.begin(); a != selected_chainids.end(); a++) {
807
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
808
if (*a == (*q)->name()) {
816
* Renames the first selected chain.
818
void ECA_CHAINSETUP::rename_chain(const string& name)
820
for(vector<string>::const_iterator a = selected_chainids.begin(); a != selected_chainids.end(); a++) {
821
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
822
if (*a == (*q)->name()) {
831
* Selects all chains present in this chainsetup.
833
void ECA_CHAINSETUP::select_all_chains(void)
835
vector<CHAIN*>::const_iterator p = chains.begin();
836
selected_chainids.resize(0);
837
while(p != chains.end()) {
838
selected_chainids.push_back((*p)->name());
844
* Returns the index number of first selected chains. If no chains
845
* are selected, returns 'last_index + 1' (==chains.size()).
847
unsigned int ECA_CHAINSETUP::first_selected_chain(void) const
849
const vector<string>& schains = selected_chains();
850
vector<string>::const_iterator o = schains.begin();
851
unsigned int p = chains.size();
852
while(o != schains.end()) {
853
for(p = 0; p != chains.size(); p++) {
854
if (chains[p]->name() == *o)
863
* Toggles chain muting of all selected chains.
865
* @pre is_locked() != true
867
void ECA_CHAINSETUP::toggle_chain_muting(void)
870
DBC_REQUIRE(is_locked() != true);
873
for(vector<string>::const_iterator a = selected_chainids.begin(); a != selected_chainids.end(); a++) {
874
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
875
if (*a == (*q)->name()) {
876
if ((*q)->is_muted())
877
(*q)->toggle_muting(false);
879
(*q)->toggle_muting(true);
886
* Toggles chain bypass of all selected chains.
888
* @pre is_locked() != true
890
void ECA_CHAINSETUP::toggle_chain_bypass(void)
893
DBC_REQUIRE(is_locked() != true);
896
for(vector<string>::const_iterator a = selected_chainids.begin(); a != selected_chainids.end(); a++) {
897
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
898
if (*a == (*q)->name()) {
899
if ((*q)->is_processing())
900
(*q)->toggle_processing(false);
902
(*q)->toggle_processing(true);
908
const ECA_CHAINSETUP_BUFPARAMS& ECA_CHAINSETUP::active_buffering_parameters(void) const
910
return impl_repp->bmode_active_rep;
913
const ECA_CHAINSETUP_BUFPARAMS& ECA_CHAINSETUP::override_buffering_parameters(void) const
915
return impl_repp->bmode_override_rep;
918
vector<string> ECA_CHAINSETUP::chain_names(void) const
920
vector<string> result;
921
vector<CHAIN*>::const_iterator p = chains.begin();
922
while(p != chains.end()) {
923
result.push_back((*p)->name());
929
vector<string> ECA_CHAINSETUP::audio_input_names(void) const
931
vector<string> result;
932
vector<AUDIO_IO*>::const_iterator p = inputs.begin();
933
while(p != inputs.end()) {
934
result.push_back((*p)->label());
940
vector<string> ECA_CHAINSETUP::audio_output_names(void) const
942
vector<string> result;
943
vector<AUDIO_IO*>::const_iterator p = outputs.begin();
944
while(p != outputs.end()) {
945
result.push_back((*p)->label());
951
vector<string> ECA_CHAINSETUP::get_attached_chains_to_input(AUDIO_IO* aiod) const
955
vector<CHAIN*>::const_iterator q = chains.begin();
956
while(q != chains.end()) {
957
if (aiod == inputs[(*q)->connected_input()]) {
958
res.push_back((*q)->name());
966
vector<string> ECA_CHAINSETUP::get_attached_chains_to_output(AUDIO_IO* aiod) const
970
vector<CHAIN*>::const_iterator q = chains.begin();
971
while(q != chains.end()) {
972
if (aiod == outputs[(*q)->connected_output()]) {
973
res.push_back((*q)->name());
981
int ECA_CHAINSETUP::number_of_attached_chains_to_input(AUDIO_IO* aiod) const
985
vector<CHAIN*>::const_iterator q = chains.begin();
986
while(q != chains.end()) {
987
if (aiod == inputs[(*q)->connected_input()]) {
996
int ECA_CHAINSETUP::number_of_attached_chains_to_output(AUDIO_IO* aiod) const
1000
vector<CHAIN*>::const_iterator q = chains.begin();
1001
while(q != chains.end()) {
1002
if (aiod == outputs[(*q)->connected_output()]) {
1012
* Output object is realtime target if it is not
1013
* connected to any chains with non-realtime inputs.
1014
* In other words all data coming to a rt target
1015
* output comes from realtime devices.
1017
bool ECA_CHAINSETUP::is_realtime_target_output(int output_id) const
1020
bool output_found = false;
1021
vector<CHAIN*>::const_iterator q = chains.begin();
1022
while(q != chains.end()) {
1023
if ((*q)->connected_output() == output_id) {
1024
output_found = true;
1025
AUDIO_IO_DEVICE* p = dynamic_cast<AUDIO_IO_DEVICE*>(inputs[(*q)->connected_input()]);
1032
if (output_found == true && result == true)
1033
ECA_LOG_MSG(ECA_LOGGER::system_objects,"slave output detected: " + outputs[output_id]->label());
1040
vector<string> ECA_CHAINSETUP::get_attached_chains_to_iodev(const string& filename) const
1042
vector<AUDIO_IO*>::size_type p;
1045
while (p < inputs.size()) {
1046
if (inputs[p]->label() == filename)
1047
return get_attached_chains_to_input(inputs[p]);
1052
while (p < outputs.size()) {
1053
if (outputs[p]->label() == filename)
1054
return get_attached_chains_to_output(outputs[p]);
1057
return vector<string> (0);
1061
* Returns number of realtime audio input objects.
1063
int ECA_CHAINSETUP::number_of_chain_operators(void) const
1066
vector<CHAIN*>::const_iterator q = chains.begin();
1067
while(q != chains.end()) {
1068
cops += (*q)->number_of_chain_operators();
1075
* Returns true if the connected chainsetup contains at least
1076
* one realtime audio input or output.
1078
bool ECA_CHAINSETUP::has_realtime_objects(void) const
1080
if (number_of_realtime_inputs() > 0 ||
1081
number_of_realtime_outputs() > 0)
1088
* Returns true if the connected chainsetup contains at least
1089
* one nonrealtime audio input or output.
1091
bool ECA_CHAINSETUP::has_nonrealtime_objects(void) const
1093
if (static_cast<int>(inputs_direct_rep.size() + outputs_direct_rep.size()) >
1094
number_of_realtime_inputs() + number_of_realtime_outputs())
1101
* Returns a string containing currently active chainsetup
1102
* options and settings. Syntax is the same as used for
1103
* saved chainsetup files.
1105
string ECA_CHAINSETUP::options_to_string(void) const
1107
return cparser_rep.general_options_to_string();
1111
* Returns number of realtime audio input objects.
1113
int ECA_CHAINSETUP::number_of_realtime_inputs(void) const
1116
for(size_t n = 0; n < inputs_direct_rep.size(); n++) {
1117
AUDIO_IO_DEVICE* p = dynamic_cast<AUDIO_IO_DEVICE*>(inputs_direct_rep[n]);
1124
* Returns number of realtime audio output objects.
1126
int ECA_CHAINSETUP::number_of_realtime_outputs(void) const
1129
for(size_t n = 0; n < outputs_direct_rep.size(); n++) {
1130
AUDIO_IO_DEVICE* p = dynamic_cast<AUDIO_IO_DEVICE*>(outputs_direct_rep[n]);
1137
* Returns number of non-realtime audio input objects.
1139
int ECA_CHAINSETUP::number_of_non_realtime_inputs(void) const
1141
return inputs.size() - number_of_realtime_inputs();
1145
* Returns number of non-realtime audio input objects.
1147
int ECA_CHAINSETUP::number_of_non_realtime_outputs(void) const
1149
return outputs.size() - number_of_realtime_outputs();
1153
* Returns a pointer to the manager handling audio object 'aobj'.
1155
* @return 0 if 'aobj' is not handled by any manager
1157
AUDIO_IO_MANAGER* ECA_CHAINSETUP::get_audio_object_manager(AUDIO_IO* aio) const
1159
for(vector<AUDIO_IO_MANAGER*>::const_iterator q = aio_managers_rep.begin(); q != aio_managers_rep.end(); q++) {
1160
if ((*q)->is_managed_type(aio) &&
1161
(*q)->get_object_id(aio) != -1) {
1162
ECA_LOG_MSG(ECA_LOGGER::system_objects,
1163
"Found object manager \"" +
1166
aio->label() + "\".");
1175
* Returns a pointer to the manager handling audio
1176
* objects of type 'aobj'.
1178
* @return 0 if 'aobj' type is not handled by any manager
1180
AUDIO_IO_MANAGER* ECA_CHAINSETUP::get_audio_object_type_manager(AUDIO_IO* aio) const
1182
for(vector<AUDIO_IO_MANAGER*>::const_iterator q = aio_managers_rep.begin(); q != aio_managers_rep.end(); q++) {
1183
if ((*q)->is_managed_type(aio) == true) {
1184
ECA_LOG_MSG(ECA_LOGGER::system_objects,
1185
"Found object manager \"" +
1187
"\" for aio type \"" +
1188
aio->name() + "\".");
1197
* If 'amgr' implements the ECA_ENGINE_DRIVER interface,
1198
* it is registered as the active driver.
1200
void ECA_CHAINSETUP::register_engine_driver(AUDIO_IO_MANAGER* amgr)
1202
ECA_ENGINE_DRIVER* driver = dynamic_cast<ECA_ENGINE_DRIVER*>(amgr);
1205
engine_driver_repp = driver;
1206
ECA_LOG_MSG(ECA_LOGGER::system_objects,
1207
"Registered audio i/o manager \"" +
1209
"\" as the current engine driver.");
1214
* Registers audio object to a manager. If no managers are
1215
* available for object's type, and it can create one,
1216
* a new manager is created.
1218
void ECA_CHAINSETUP::register_audio_object_to_manager(AUDIO_IO* aio)
1220
AUDIO_IO_MANAGER* mgr = get_audio_object_type_manager(aio);
1222
mgr = aio->create_object_manager();
1224
ECA_LOG_MSG(ECA_LOGGER::system_objects,
1225
"Creating object manager \"" +
1228
aio->name() + "\".");
1229
aio_managers_rep.push_back(mgr);
1230
propagate_audio_io_manager_options();
1231
mgr->register_object(aio);
1233
/* in case manager is also a driver */
1234
register_engine_driver(mgr);
1238
mgr->register_object(aio);
1243
* Unregisters audio object from manager.
1245
void ECA_CHAINSETUP::unregister_audio_object_from_manager(AUDIO_IO* aio)
1247
AUDIO_IO_MANAGER* mgr = get_audio_object_manager(aio);
1249
int id = mgr->get_object_id(aio);
1251
ECA_LOG_MSG(ECA_LOGGER::system_objects,
1252
"Unregistering object \"" +
1254
"\" from manager \"" +
1255
mgr->name() + "\".");
1256
mgr->unregister_object(id);
1262
* Propagates to set manager options to all existing
1263
* audio i/o manager objects.
1265
void ECA_CHAINSETUP::propagate_audio_io_manager_options(void)
1267
for(vector<AUDIO_IO_MANAGER*>::const_iterator q = aio_managers_rep.begin(); q != aio_managers_rep.end(); q++) {
1268
if (aio_manager_option_map_rep.find((*q)->name()) !=
1269
aio_manager_option_map_rep.end()) {
1271
const string& optstring = aio_manager_option_map_rep[(*q)->name()];
1272
int numparams = (*q)->number_of_params();
1273
for(int n = 0; n < numparams; n++) {
1274
(*q)->set_parameter(n + 1, kvu_get_argument_number(n + 1, optstring));
1275
ECA_LOG_MSG(ECA_LOGGER::system_objects,
1277
(*q)->name() + "\", " +
1278
kvu_numtostr(n + 1) + ". parameter set to \"" +
1279
(*q)->get_parameter(n + 1) + "\".");
1286
* Helper function used by add_input() and add_output().
1288
* All audio object creates go through this function,
1289
* so this is good place to do global operations that
1290
* apply to both inputs and outputs.
1292
AUDIO_IO* ECA_CHAINSETUP::add_audio_object_helper(AUDIO_IO* aio)
1294
AUDIO_IO* retobj = aio;
1296
AUDIO_IO_DEVICE* p = dynamic_cast<AUDIO_IO_DEVICE*>(aio);
1297
LOOP_DEVICE* q = dynamic_cast<LOOP_DEVICE*>(aio);
1298
if (p == 0 && q == 0) {
1299
/* not a realtime or loop device */
1300
retobj = new AUDIO_IO_DB_CLIENT(&impl_repp->pserver_rep, aio, false);
1307
* Helper function used by remove_audio_object().
1309
void ECA_CHAINSETUP::remove_audio_object_proxy(AUDIO_IO* aio)
1311
AUDIO_IO_DB_CLIENT* p = dynamic_cast<AUDIO_IO_DB_CLIENT*>(aio);
1313
/* a proxied object */
1314
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Delete proxy object " + aio->label() + ".");
1321
* Helper function used bu remove_audio_object() to remove input
1322
* and output loop devices.
1324
void ECA_CHAINSETUP::remove_audio_object_loop(const string& label, AUDIO_IO* aio, int dir)
1326
int rdir = (dir == cs_dir_input ? cs_dir_output : cs_dir_input);
1328
/* loop devices are registered simultaneously to both input
1329
* and output object vectors, so they have to be removed
1330
* from both, but deleted only once */
1332
remove_audio_object_impl(label, rdir, false);
1334
/* we also need to remove the loop device from
1335
* the loop_map table */
1337
map<string,LOOP_DEVICE*>::iterator iter = loop_map.begin();
1338
while(iter != loop_map.end()) {
1339
if (iter->second == aio) {
1340
loop_map.erase(iter);
1348
* Adds a new input object and attaches it to selected chains.
1350
* If double-buffering is enabled (double_buffering() == true),
1351
* and the object in question is not a realtime object, it
1352
* is wrapped in a AUDIO_IO_DB_CLIENT object before
1353
* inserted to the chainsetup. Otherwise object is added
1356
* Ownership of the insert object is transfered to
1360
* @pre is_enabled() != true
1361
* @post inputs.size() == old(inputs.size() + 1
1363
void ECA_CHAINSETUP::add_input(AUDIO_IO* aio)
1366
DBC_REQUIRE(aio != 0);
1367
DBC_REQUIRE(is_enabled() != true);
1368
DBC_DECLARE(size_t old_inputs_size = inputs.size());
1371
aio->set_io_mode(AUDIO_IO::io_read);
1372
aio->set_audio_format(default_audio_format());
1373
aio->set_buffersize(buffersize());
1375
register_audio_object_to_manager(aio);
1376
AUDIO_IO* layerobj = add_audio_object_helper(aio);
1377
inputs.push_back(layerobj);
1378
inputs_direct_rep.push_back(aio);
1379
input_start_pos.push_back(0);
1380
attach_input_to_selected_chains(layerobj);
1383
DBC_ENSURE(inputs.size() == old_inputs_size + 1);
1384
DBC_ENSURE(inputs.size() == inputs_direct_rep.size());
1389
* Add a new output object and attach it to selected chains.
1391
* If double-buffering is enabled (double_buffering() == true),
1392
* and the object in question is not a realtime object, it
1393
* is wrapped in a AUDIO_IO_DB_CLIENT object before
1394
* inserted to the chainsetup. Otherwise object is added
1397
* Ownership of the insert object is transfered to
1401
* @pre is_enabled() != true
1402
* @post outputs.size() == outputs_direct_rep.size()
1404
void ECA_CHAINSETUP::add_output(AUDIO_IO* aio, bool truncate)
1407
DBC_REQUIRE(aio != 0);
1408
DBC_REQUIRE(is_enabled() != true);
1409
DBC_DECLARE(size_t old_outputs_size = outputs.size());
1412
aio->set_audio_format(default_audio_format());
1413
aio->set_buffersize(buffersize());
1414
if (truncate == true)
1415
aio->set_io_mode(AUDIO_IO::io_write);
1417
aio->set_io_mode(AUDIO_IO::io_readwrite);
1419
register_audio_object_to_manager(aio);
1420
AUDIO_IO* layerobj = add_audio_object_helper(aio);
1421
outputs.push_back(layerobj);
1422
outputs_direct_rep.push_back(aio);
1423
output_start_pos.push_back(0);
1424
attach_output_to_selected_chains(layerobj);
1427
DBC_ENSURE(outputs.size() == old_outputs_size + 1);
1428
DBC_ENSURE(outputs.size() == outputs_direct_rep.size());
1432
* Erases an element matching 'obj' from 'vec'. At most one element
1433
* is removed. The function does not delete the referred object, just
1434
* removes it from the vector.
1436
static void priv_erase_object(std::vector<AUDIO_IO*>* vec, const AUDIO_IO* obj)
1438
vector<AUDIO_IO*>::iterator p = vec->begin();
1439
while(p != vec->end()) {
1449
* Removes the labeled audio object from this chainsetup.
1451
* @pre is_enabled() != true
1453
void ECA_CHAINSETUP::remove_audio_object_impl(const string& label, int dir, bool destroy)
1456
DBC_REQUIRE(is_enabled() != true);
1459
vector<AUDIO_IO*> *objs = (dir == cs_dir_input ? &inputs : &outputs);
1460
vector<AUDIO_IO*> *objs_dir = (dir == cs_dir_input ? &inputs_direct_rep : &outputs_direct_rep);
1461
DBC_DECLARE(size_t oldsize = objs->size());
1462
AUDIO_IO *obj_to_remove = 0, *obj_dir_to_remove = NULL;
1463
int remove_index = -1;
1466
* - objs and objs_dir vectors are always of the same size
1467
* - for non-proxied objects 'objs[n] == objs_dir[n]' for all n
1470
for(size_t n = 0; n < objs->size(); n++) {
1471
if ((*objs)[n]->label() == label) {
1472
obj_to_remove = (*objs)[n];
1473
obj_dir_to_remove = (*objs_dir)[n];
1474
remove_index = static_cast<int>(n);
1478
if (obj_to_remove) {
1479
DBC_CHECK(remove_index >= 0);
1480
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Removing object " + obj_to_remove->label() + ".");
1482
/* disconnect object from chains */
1483
vector<CHAIN*>::iterator q = chains.begin();
1484
while(q != chains.end()) {
1485
if (dir == cs_dir_input) {
1486
if ((*q)->connected_input() == remove_index) {
1487
(*q)->disconnect_input();
1491
if ((*q)->connected_output() == remove_index) {
1492
(*q)->disconnect_output();
1498
/* unregister from manager (always the objs_dir object) */
1499
unregister_audio_object_from_manager((*objs_dir)[remove_index]);
1501
/* delete proxy object if any */
1502
if (obj_to_remove != obj_dir_to_remove) {
1503
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Audio object proxied: " + obj_to_remove->label());
1504
remove_audio_object_proxy(obj_to_remove);
1507
priv_erase_object(objs, obj_to_remove);
1508
priv_erase_object(objs_dir, obj_dir_to_remove);
1510
LOOP_DEVICE* loop_dev = dynamic_cast<LOOP_DEVICE*>(obj_dir_to_remove);
1511
if (loop_dev != 0 && destroy == true) {
1512
/* note: destroy must be true to limit recursion */
1513
remove_audio_object_loop(label, obj_dir_to_remove, dir);
1516
/* finally actually delete the object */
1517
if (destroy == true)
1518
delete obj_dir_to_remove;
1522
DBC_ENSURE(objs->size() == objs_dir->size());
1523
DBC_ENSURE(oldsize == objs->size() + 1);
1528
* Removes the labeled audio input from this chainsetup.
1530
* @pre is_enabled() != true
1532
void ECA_CHAINSETUP::remove_audio_input(const string& label)
1535
DBC_REQUIRE(is_enabled() != true);
1536
DBC_DECLARE(size_t oldsize = inputs.size());
1539
remove_audio_object_impl(label, cs_dir_input, true);
1542
DBC_ENSURE(inputs.size() == inputs_direct_rep.size());
1543
DBC_ENSURE(oldsize == inputs.size() + 1);
1548
* Removes the labeled audio output from this chainsetup.
1550
* @pre is_enabled() != true
1552
void ECA_CHAINSETUP::remove_audio_output(const string& label)
1555
DBC_REQUIRE(is_enabled() != true);
1556
DBC_DECLARE(size_t oldsize = outputs.size());
1559
remove_audio_object_impl(label, cs_dir_output, true);
1562
DBC_ENSURE(outputs.size() == outputs_direct_rep.size());
1563
DBC_ENSURE(oldsize == outputs.size() + 1);
1568
* Print trace messages when opening audio file 'aio'.
1572
void ECA_CHAINSETUP::audio_object_open_info(const AUDIO_IO* aio)
1575
DBC_REQUIRE(aio != 0);
1578
string temp = "Opened ";
1580
temp += (aio->io_mode() == AUDIO_IO::io_read) ? "input" : "output";
1581
temp += " \"" + aio->label();
1582
temp += "\", mode \"";
1583
if (aio->io_mode() == AUDIO_IO::io_read) temp += "read";
1584
if (aio->io_mode() == AUDIO_IO::io_write) temp += "write";
1585
if (aio->io_mode() == AUDIO_IO::io_readwrite) temp += "read/write (update)";
1587
temp += aio->format_info();
1589
ECA_LOG_MSG(ECA_LOGGER::info, temp);
1594
* Adds a new MIDI-device object.
1597
* @pre is_enabled() != true
1598
* @post midi_devices.size() > 0
1600
void ECA_CHAINSETUP::add_midi_device(MIDI_IO* mididev)
1603
DBC_REQUIRE(mididev != 0);
1604
DBC_REQUIRE(is_enabled() != true);
1607
midi_devices.push_back(mididev);
1608
impl_repp->midi_server_rep.register_client(mididev);
1611
DBC_ENSURE(midi_devices.size() > 0);
1616
* Remove an MIDI-device by the name 'mdev_name'.
1618
* @pre is_enabled() != true
1620
void ECA_CHAINSETUP::remove_midi_device(const string& mdev_name)
1623
DBC_REQUIRE(is_enabled() != true);
1626
for(vector<MIDI_IO*>::iterator q = midi_devices.begin(); q != midi_devices.end(); q++) {
1627
if (mdev_name == (*q)->label()) {
1629
midi_devices.erase(q);
1635
const CHAIN* ECA_CHAINSETUP::get_chain_with_name(const string& name) const
1637
vector<CHAIN*>::const_iterator p = chains.begin();
1638
while(p != chains.end()) {
1639
if ((*p)->name() == name) return(*p);
1646
* Returns a non-zero index for chain 'name'. If the chain
1647
* does not exist, -1 is returned.
1649
* The chain index can be used with ECA::chainsetup_edit_t
1650
* items passed to ECA_CHAINSETUP::execute_edit().
1652
* Note: Mapping of chain names to indices can change if any
1653
* chains are either added or removed. If that happens,
1654
* the indices need to be recalculated.
1656
int ECA_CHAINSETUP::get_chain_index(const string& name) const
1659
vector<CHAIN*>::const_iterator p = chains.begin();
1660
for(int n = 1; p != chains.end(); n++) {
1661
if ((*p)->name() == name) {
1671
* Attaches input 'obj' to all selected chains.
1673
* @pre is_locked() != true
1675
void ECA_CHAINSETUP::attach_input_to_selected_chains(const AUDIO_IO* obj)
1678
DBC_REQUIRE(obj != 0);
1679
DBC_REQUIRE(is_locked() != true);
1683
vector<AUDIO_IO*>::size_type c = 0;
1685
while (c < inputs.size()) {
1686
if (inputs[c] == obj) {
1687
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
1688
if ((*q)->connected_input() == static_cast<int>(c)) {
1689
(*q)->disconnect_input();
1692
temp += "Assigning file to chains:";
1693
for(vector<string>::const_iterator p = selected_chainids.begin(); p!= selected_chainids.end(); p++) {
1694
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
1695
if (*p == (*q)->name()) {
1696
(*q)->connect_input(c);
1704
ECA_LOG_MSG(ECA_LOGGER::system_objects, temp);
1708
* Attaches output 'obj' to all selected chains.
1710
* @pre is_locked() != true
1712
void ECA_CHAINSETUP::attach_output_to_selected_chains(const AUDIO_IO* obj)
1715
DBC_REQUIRE(obj != 0);
1716
DBC_REQUIRE(is_locked() != true);
1720
vector<AUDIO_IO*>::size_type c = 0;
1721
while (c < outputs.size()) {
1722
if (outputs[c] == obj) {
1723
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
1724
if ((*q)->connected_output() == static_cast<int>(c)) {
1725
(*q)->disconnect_output();
1728
temp += "Assigning file to chains:";
1729
for(vector<string>::const_iterator p = selected_chainids.begin(); p!= selected_chainids.end(); p++) {
1730
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
1731
if (*p == (*q)->name()) {
1732
(*q)->connect_output(static_cast<int>(c));
1740
ECA_LOG_MSG(ECA_LOGGER::system_objects, temp);
1744
* Returns true if 'aobj' is a pointer to some input
1747
bool ECA_CHAINSETUP::ok_audio_object(const AUDIO_IO* aobj) const
1749
if (ok_audio_object_helper(aobj, inputs) == true ||
1750
ok_audio_object_helper(aobj, outputs) == true ) return(true);
1756
bool ECA_CHAINSETUP::ok_audio_object_helper(const AUDIO_IO* aobj,
1757
const vector<AUDIO_IO*>& aobjs)
1759
for(size_t n = 0; n < aobjs.size(); n++) {
1760
if (aobjs[n] == aobj) return(true);
1765
void ECA_CHAINSETUP::check_object_samplerate(const AUDIO_IO* obj,
1766
SAMPLE_SPECS::sample_rate_t srate) throw(ECA_ERROR&)
1768
if (obj->samples_per_second() != srate) {
1769
throw(ECA_ERROR("ECA-CHAINSETUP",
1770
string("All audio objects must have a common") +
1771
" sampling rate; sampling rate of audio object \"" +
1773
"\" differs from engine rate (" +
1774
kvu_numtostr(obj->samples_per_second()) +
1776
kvu_numtostr(srate) +
1777
"); unable to continue."));
1781
void ECA_CHAINSETUP::enable_audio_object_helper(AUDIO_IO* aobj) const
1783
aobj->set_buffersize(buffersize());
1784
AUDIO_IO_DEVICE* dev = dynamic_cast<AUDIO_IO_DEVICE*>(aobj);
1786
dev->toggle_max_buffers(max_buffers());
1787
dev->toggle_ignore_xruns(ignore_xruns());
1789
if (aobj->is_open() == false) {
1790
const std::string req_format = ECA_OBJECT_FACTORY::audio_object_format_to_eos(aobj);
1792
const std::string act_format =
1793
ECA_OBJECT_FACTORY::audio_object_format_to_eos(aobj);
1794
if (act_format != req_format) {
1795
DBC_CHECK(aobj->locked_audio_format() == true);
1796
ECA_LOG_MSG(ECA_LOGGER::info,
1797
"NOTE: using existing audio parameters " + act_format +
1798
" for object '" + aobj->label() + "' (tried to open with " +
1802
if (aobj->is_open() == true) {
1803
aobj->seek_position_in_samples(aobj->position_in_samples());
1804
audio_object_open_info(aobj);
1809
* Enable chainsetup. Opens all devices and reinitializes all
1810
* chain operators if necessary.
1812
* This action is performed before connecting the chainsetup
1813
* to a engine object (for instance ECA_ENGINE).
1815
* @pre is_locked() != true
1816
* @post is_enabled() == true
1818
void ECA_CHAINSETUP::enable(void) throw(ECA_ERROR&)
1821
DBC_REQUIRE(is_locked() != true);
1825
if (is_enabled_rep != true) {
1827
/* 1. check that current buffersize is supported by all devices */
1828
long int locked_bsize = check_for_locked_buffersize();
1829
if (locked_bsize != -1) {
1830
set_buffersize(locked_bsize);
1833
/* 2. select and enable buffering parameters */
1834
select_active_buffering_mode();
1835
enable_active_buffering_mode();
1837
/* 3.1 open input devices */
1838
for(vector<AUDIO_IO*>::iterator q = inputs.begin(); q != inputs.end(); q++) {
1839
enable_audio_object_helper(*q);
1840
if ((*q)->is_open() != true) {
1841
throw(ECA_ERROR("ECA-CHAINSETUP", "Open failed without explicit exception!"));
1845
/* 3.2. make sure that all input devices have a common
1847
SAMPLE_SPECS::sample_rate_t first_locked_srate = 0;
1848
for(vector<AUDIO_IO*>::iterator q = inputs.begin(); q != inputs.end(); q++) {
1849
if (first_locked_srate == 0) {
1850
if ((*q)->locked_audio_format() == true) {
1851
first_locked_srate = (*q)->samples_per_second();
1853
/* set chainsetup sampling rate to 'first_srate'. */
1854
set_samples_per_second(first_locked_srate);
1858
check_object_samplerate(*q, first_locked_srate);
1862
/* 4. open output devices */
1863
for(vector<AUDIO_IO*>::iterator q = outputs.begin(); q != outputs.end(); q++) {
1864
enable_audio_object_helper(*q);
1865
if ((*q)->is_open() != true) {
1866
throw(ECA_ERROR("ECA-CHAINSETUP", "Open failed without explicit exception!"));
1868
if (first_locked_srate == 0) {
1869
if ((*q)->locked_audio_format() == true) {
1870
first_locked_srate = (*q)->samples_per_second();
1872
/* set chainsetup sampling rate to 'first_srate'. */
1873
set_samples_per_second(first_locked_srate);
1877
check_object_samplerate(*q, first_locked_srate);
1881
/* 5. in case there were no objects with locked srates */
1882
if (first_locked_srate == 0) {
1883
if (inputs.size() > 0) {
1884
/* set chainsetup srate to that of the first input */
1885
set_samples_per_second(inputs[0]->samples_per_second());
1889
/* 6. enable the MIDI server */
1890
if (impl_repp->midi_server_rep.is_enabled() != true &&
1891
midi_devices.size() > 0) {
1892
impl_repp->midi_server_rep.set_schedrealtime(raised_priority());
1893
impl_repp->midi_server_rep.set_schedpriority(get_sched_priority());
1894
impl_repp->midi_server_rep.enable();
1897
/* 7. enable all MIDI-devices */
1898
for(vector<MIDI_IO*>::iterator q = midi_devices.begin(); q != midi_devices.end(); q++) {
1899
(*q)->toggle_nonblocking_mode(true);
1900
if ((*q)->is_open() != true) {
1902
if ((*q)->is_open() != true) {
1903
throw(ECA_ERROR("ECA-CHAINSETUP",
1904
string("Unable to open MIDI-device: ") +
1911
/* 8. calculate chainsetup length */
1912
calculate_processing_length();
1915
is_enabled_rep = true;
1917
catch(AUDIO_IO::SETUP_ERROR& e) {
1918
ECA_LOG_MSG(ECA_LOGGER::system_objects,
1919
"Connecting chainsetup failed, throwing an SETUP_ERROR exception.");
1920
throw(ECA_ERROR("ECA-CHAINSETUP",
1921
string("Enabling chainsetup: ")
1925
ECA_LOG_MSG(ECA_LOGGER::system_objects,
1926
"Connecting chainsetup failed, throwing a generic exception.");
1931
DBC_ENSURE(is_enabled() == true);
1938
* Disable chainsetup. Closes all devices.
1940
* This action is performed before disconnecting the
1941
* chainsetup from a engine object (for instance
1944
* @pre is_locked() != true
1945
* @post is_enabled() != true
1947
void ECA_CHAINSETUP::disable(void)
1950
DBC_REQUIRE(is_locked() != true);
1953
/* calculate chainsetup length in case it has changed during processing */
1954
calculate_processing_length();
1956
if (is_enabled_rep == true) {
1957
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Closing chainsetup \"" + name() + "\"");
1958
for(vector<AUDIO_IO*>::iterator q = inputs.begin(); q != inputs.end(); q++) {
1959
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Closing audio device/file \"" + (*q)->label() + "\".");
1960
if ((*q)->is_open() == true) (*q)->close();
1963
for(vector<AUDIO_IO*>::iterator q = outputs.begin(); q != outputs.end(); q++) {
1964
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Closing audio device/file \"" + (*q)->label() + "\".");
1965
if ((*q)->is_open() == true) (*q)->close();
1968
if (impl_repp->midi_server_rep.is_enabled() == true) impl_repp->midi_server_rep.disable();
1969
for(vector<MIDI_IO*>::iterator q = midi_devices.begin(); q != midi_devices.end(); q++) {
1970
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Closing midi device \"" + (*q)->label() + "\".");
1971
if ((*q)->is_open() == true) (*q)->close();
1974
is_enabled_rep = false;
1978
DBC_ENSURE(is_enabled() != true);
1983
* Executes chainsetup edit 'edit'.
1985
* @return true if succesful, false if edit cannot
1988
bool ECA_CHAINSETUP::execute_edit(const chainsetup_edit_t& edit)
1992
ECA_LOG_MSG(ECA_LOGGER::user_objects,
1993
"Executing edit type of " +
1994
kvu_numtostr(static_cast<int>(edit.type)));
1996
if (edit.cs_ptr != this) {
1997
ECA_LOG_MSG(ECA_LOGGER::errors,
1998
"ERROR: chainsetup edit executed on wrong object");
2004
case edit_cop_set_param:
2006
if (edit.m.cop_set_param.chain < 1 ||
2007
edit.m.cop_set_param.chain > static_cast<int>(chains.size())) {
2011
CHAIN *ch = chains[edit.m.cop_set_param.chain - 1];
2012
ch->set_parameter(edit.m.cop_set_param.op,
2013
edit.m.cop_set_param.param,
2014
edit.m.cop_set_param.value);
2017
case edit_ctrl_set_param:
2019
if (edit.m.ctrl_set_param.chain < 1 ||
2020
edit.m.ctrl_set_param.chain > static_cast<int>(chains.size())) {
2024
CHAIN *ch = chains[edit.m.ctrl_set_param.chain - 1];
2025
ch->set_controller_parameter(edit.m.ctrl_set_param.op,
2026
edit.m.ctrl_set_param.param,
2027
edit.m.ctrl_set_param.value);
2032
DBC_NEVER_REACHED();
2034
ECA_LOG_MSG(ECA_LOGGER::info,
2035
"Unknown edit of type " +
2036
kvu_numtostr(static_cast<int>(edit.type)));
2045
* Updates the chainsetup processing length based on
2046
* 1) requested length, 2) lengths of individual
2047
* input objects, and 3) looping settings.
2049
void ECA_CHAINSETUP::calculate_processing_length(void)
2051
long int max_input_length = 0;
2052
for(unsigned int n = 0; n < inputs.size(); n++) {
2053
if (inputs[n]->length_in_samples() > max_input_length)
2054
max_input_length = inputs[n]->length_in_samples();
2057
/* note! here we set the _actual_ length of the
2059
set_length_in_samples(max_input_length);
2061
if (looping_enabled() == true) {
2062
if (max_length_set() != true &&
2063
max_input_length > 0) {
2064
/* looping but length not set */
2065
ECA_LOG_MSG(ECA_LOGGER::info,
2066
"Setting loop point to "
2067
+ kvu_numtostr(length_in_seconds_exact()) + ".");
2068
set_max_length_in_samples(max_input_length);
2074
* Check whether the buffersize is locked to some
2077
* @return -1 if not locked, otherwise the locked
2080
long int ECA_CHAINSETUP::check_for_locked_buffersize(void) const
2082
long int result = -1;
2083
#ifdef ECA_COMPILE_JACK
2085
string cname = "ecasound-ctrl-" + kvu_numtostr(pid);
2088
for(size_t n = 0; n < inputs_direct_rep.size(); n++) {
2089
if (inputs_direct_rep[n]->name() == "JACK interface") ++jackobjs;
2091
for(size_t n = 0; n < outputs_direct_rep.size(); n++) {
2092
if (outputs_direct_rep[n]->name() == "JACK interface") ++jackobjs;
2095
/* contact jackd only if there is at least one jack audio object
2098
jack_client_t *client = jack_client_open(cname.c_str(), JackNullOption, NULL);
2100
// xxx = static_cast<long int>(jack_get_sample_rate(client);
2101
result = static_cast<long int>(jack_get_buffer_size(client));
2103
ECA_LOG_MSG(ECA_LOGGER::user_objects,
2104
"jackd buffersize check returned " +
2105
kvu_numtostr(result) + ".");
2107
jack_client_close(client);
2112
ECA_LOG_MSG(ECA_LOGGER::user_objects,
2113
"unable to perform jackd buffersize check.");
2116
DBC_CHECK(client == 0);
2123
* Reimplemented from ECA_CHAINSETUP_POSITION.
2125
void ECA_CHAINSETUP::set_samples_per_second(SAMPLE_SPECS::sample_rate_t new_value)
2127
/* not necessarily a problem */
2128
DBC_CHECK(is_locked() != true);
2130
ECA_LOG_MSG(ECA_LOGGER::user_objects,
2131
"sample rate change, chainsetup " +
2134
kvu_numtostr(new_value) + ".");
2136
for(vector<AUDIO_IO*>::iterator q = inputs.begin(); q != inputs.end(); q++) {
2137
(*q)->set_samples_per_second(new_value);
2140
for(vector<AUDIO_IO*>::iterator q = outputs.begin(); q != outputs.end(); q++) {
2141
(*q)->set_samples_per_second(new_value);
2144
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
2145
(*q)->set_samples_per_second(new_value);
2148
ECA_CHAINSETUP_POSITION::set_samples_per_second(new_value);
2151
static void priv_seek_position_helper(std::vector<AUDIO_IO*>* objs, SAMPLE_SPECS::sample_pos_t pos, const std::string& tag)
2153
for(vector<AUDIO_IO*>::iterator q = objs->begin(); q != objs->end(); q++) {
2154
/* note: don't try to seek real-time devices (only
2155
* allowed exception, try seeking all other
2157
if (dynamic_cast<AUDIO_IO_DEVICE*>(*q) == 0) {
2158
(*q)->seek_position_in_samples(pos);
2159
/* note: report if object claims it supports seeking, but
2160
* in fact the seek failed */
2161
if ((*q)->supports_seeking() == true) {
2162
if (pos <= (*q)->length_in_samples() &&
2163
(*q)->position_in_samples() != pos)
2164
ECA_LOG_MSG(ECA_LOGGER::info,
2165
"WARNING: sample accurate seek failed with " +
2166
tag + " \"" + (*q)->name() + "\"");
2173
* Reimplemented from ECA_AUDIO_POSITION.
2175
SAMPLE_SPECS::sample_pos_t ECA_CHAINSETUP::seek_position(SAMPLE_SPECS::sample_pos_t pos)
2177
ECA_LOG_MSG(ECA_LOGGER::user_objects,
2178
"seek position, chainsetup \"" +
2180
"\" to pos in sec " +
2181
kvu_numtostr(pos) + ".");
2183
if (is_enabled() == true) {
2184
if (double_buffering() == true) pserver_repp->flush();
2187
priv_seek_position_helper(&inputs, pos, "input");
2188
priv_seek_position_helper(&outputs, pos, "output");
2190
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
2191
(*q)->seek_position_in_samples(pos);
2192
if ((*q)->position_in_samples() != pos)
2193
ECA_LOG_MSG(ECA_LOGGER::info,
2194
"WARNING: sample accurate seek failed with chainop \"" +
2195
(*q)->name() + "\"");
2203
* Interprets one option. This is the most generic variant of
2204
* the interpretation routines; both global and object specific
2205
* options are handled.
2207
* @pre argu.size() > 0
2208
* @pre argu[0] == '-'
2209
* @pre is_enabled() != true
2211
* @post (option successfully interpreted && interpret_result() == true) ||
2212
* (unknown or invalid option && interpret_result() != true)
2214
void ECA_CHAINSETUP::interpret_option (const string& arg)
2217
DBC_REQUIRE(is_enabled() != true);
2220
cparser_rep.interpret_option(arg);
2224
* Interprets one option. All non-global options are ignored. Global
2225
* options can be interpreted multiple times and in any order.
2227
* @pre argu.size() > 0
2228
* @pre argu[0] == '-'
2229
* @pre is_enabled() != true
2230
* @post (option successfully interpreted && interpretation_result() == true) ||
2231
* (unknown or invalid option && interpretation_result() == false)
2233
void ECA_CHAINSETUP::interpret_global_option (const string& arg)
2236
DBC_REQUIRE(is_enabled() != true);
2239
cparser_rep.interpret_global_option(arg);
2243
* Interprets one option. All options not directly related to
2244
* ecasound objects are ignored.
2246
* @pre argu.size() > 0
2247
* @pre argu[0] == '-'
2248
* @pre is_enabled() != true
2250
* @post (option successfully interpreted && interpretation_result() == true) ||
2251
* (unknown or invalid option && interpretation_result() == false)
2253
void ECA_CHAINSETUP::interpret_object_option (const string& arg)
2256
// FIXME: this requirement is broken by eca-control.h (for
2257
// adding effects on-the-fly, just stopping the engine)
2258
// DBC_REQUIRE(is_enabled() != true);
2261
cparser_rep.interpret_object_option(arg);
2265
* Interpret a vector of options.
2267
* If any invalid options are passed us argument,
2268
* interpret_result() will be 'false', and
2269
* interpret_result_verbose() contains more detailed
2270
* error description.
2272
* @pre is_enabled() != true
2274
void ECA_CHAINSETUP::interpret_options(const vector<string>& opts)
2277
DBC_REQUIRE(is_enabled() != true);
2280
cparser_rep.interpret_options(opts);
2283
void ECA_CHAINSETUP::set_buffersize(long int value)
2285
ECA_LOG_MSG(ECA_LOGGER::system_objects, "overriding buffersize.");
2286
impl_repp->bmode_override_rep.set_buffersize(value);
2289
void ECA_CHAINSETUP::toggle_raised_priority(bool value) {
2290
ECA_LOG_MSG(ECA_LOGGER::system_objects, "overriding raised priority.");
2291
impl_repp->bmode_override_rep.toggle_raised_priority(value);
2294
void ECA_CHAINSETUP::set_sched_priority(int value)
2296
ECA_LOG_MSG(ECA_LOGGER::system_objects, "sched_priority.");
2297
impl_repp->bmode_override_rep.set_sched_priority(value);
2300
void ECA_CHAINSETUP::toggle_double_buffering(bool value)
2302
ECA_LOG_MSG(ECA_LOGGER::system_objects, "overriding doublebuffering.");
2303
impl_repp->bmode_override_rep.toggle_double_buffering(value);
2306
void ECA_CHAINSETUP::set_double_buffer_size(long int v)
2308
ECA_LOG_MSG(ECA_LOGGER::system_objects, "overriding db-size.");
2309
impl_repp->bmode_override_rep.set_double_buffer_size(v);
2312
void ECA_CHAINSETUP::toggle_max_buffers(bool v)
2314
ECA_LOG_MSG(ECA_LOGGER::system_objects, "overriding max_buffers.");
2315
impl_repp->bmode_override_rep.toggle_max_buffers(v);
2318
long int ECA_CHAINSETUP::buffersize(void) const
2320
if (impl_repp->bmode_override_rep.is_set_buffersize() == true)
2321
return impl_repp->bmode_override_rep.buffersize();
2323
return impl_repp->bmode_active_rep.buffersize();
2326
bool ECA_CHAINSETUP::raised_priority(void) const
2328
if (impl_repp->bmode_override_rep.is_set_raised_priority() == true)
2329
return impl_repp->bmode_override_rep.raised_priority();
2331
return impl_repp->bmode_active_rep.raised_priority();
2334
int ECA_CHAINSETUP::get_sched_priority(void) const
2336
if (impl_repp->bmode_override_rep.is_set_sched_priority() == true)
2337
return impl_repp->bmode_override_rep.get_sched_priority();
2339
return impl_repp->bmode_active_rep.get_sched_priority();
2342
bool ECA_CHAINSETUP::double_buffering(void) const {
2343
if (impl_repp->bmode_override_rep.is_set_double_buffering() == true)
2344
return impl_repp->bmode_override_rep.double_buffering();
2346
return impl_repp->bmode_active_rep.double_buffering();
2349
long int ECA_CHAINSETUP::double_buffer_size(void) const {
2350
if (impl_repp->bmode_override_rep.is_set_double_buffer_size() == true)
2351
return impl_repp->bmode_override_rep.double_buffer_size();
2353
return impl_repp->bmode_active_rep.double_buffer_size();
2356
bool ECA_CHAINSETUP::max_buffers(void) const {
2357
if (impl_repp->bmode_override_rep.is_set_max_buffers() == true)
2358
return impl_repp->bmode_override_rep.max_buffers();
2360
return impl_repp->bmode_active_rep.max_buffers();
2363
void ECA_CHAINSETUP::set_default_audio_format(ECA_AUDIO_FORMAT& value) {
2364
impl_repp->default_audio_format_rep = value;
2367
const ECA_AUDIO_FORMAT& ECA_CHAINSETUP::default_audio_format(void) const
2369
return impl_repp->default_audio_format_rep;
2373
* Select controllers as targets for parameter control
2375
void ECA_CHAINSETUP::set_target_to_controller(void) {
2376
vector<string> schains = selected_chains();
2377
for(vector<string>::const_iterator a = schains.begin(); a != schains.end(); a++) {
2378
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
2379
if (*a == (*q)->name()) {
2380
(*q)->selected_controller_as_target();
2388
* Add general controller to selected chainop.
2391
* @pre is_locked() != true
2392
* @pre selected_chains().size() == 1
2394
void ECA_CHAINSETUP::add_controller(GENERIC_CONTROLLER* csrc)
2397
DBC_REQUIRE(csrc != 0);
2398
DBC_REQUIRE(is_locked() != true);
2399
DBC_REQUIRE(selected_chains().size() == 1);
2402
#ifndef ECA_DISABLE_EFFECTS
2403
AUDIO_STAMP_CLIENT* p = dynamic_cast<AUDIO_STAMP_CLIENT*>(csrc->source_pointer());
2405
p->register_server(&impl_repp->stamp_server_rep);
2409
DBC_CHECK(buffersize() != 0);
2410
DBC_CHECK(samples_per_second() != 0);
2412
vector<string> schains = selected_chains();
2413
for(vector<string>::const_iterator a = schains.begin(); a != schains.end(); a++) {
2414
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
2415
if (*a == (*q)->name()) {
2416
if ((*q)->selected_target() == 0) return;
2417
(*q)->add_controller(csrc);
2425
* Add chain operator to selected chain.
2428
* @pre is_locked() != true
2429
* @pre selected_chains().size() == 1
2431
void ECA_CHAINSETUP::add_chain_operator(CHAIN_OPERATOR* cotmp)
2434
DBC_REQUIRE(cotmp != 0);
2435
DBC_REQUIRE(is_locked() != true);
2436
DBC_REQUIRE(selected_chains().size() == 1);
2439
#ifndef ECA_DISABLE_EFFECTS
2440
AUDIO_STAMP* p = dynamic_cast<AUDIO_STAMP*>(cotmp);
2442
impl_repp->stamp_server_rep.register_stamp(p);
2446
vector<string> schains = selected_chains();
2447
for(vector<string>::const_iterator p = schains.begin(); p != schains.end(); p++) {
2448
for(vector<CHAIN*>::iterator q = chains.begin(); q != chains.end(); q++) {
2449
if (*p == (*q)->name()) {
2450
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Adding chainop to chain " + (*q)->name() + ".");
2451
(*q)->add_chain_operator(cotmp);
2452
(*q)->selected_chain_operator_as_target();
2460
* If chainsetup has inputs, but no outputs, a default output is
2463
* @pre is_enabled() != true
2465
void ECA_CHAINSETUP::add_default_output(void)
2468
DBC_REQUIRE(is_enabled() != true);
2471
if (inputs.size() > 0 && outputs.size() == 0) {
2473
// No -o[:] options specified; let's use the default output
2475
select_all_chains();
2476
interpret_object_option(string("-o:") + ECA_OBJECT_FACTORY::probe_default_output_device());
2481
* If chainsetup has objects that need MIDI services,
2482
* but no MIDI-devices defined, a default MIDI-device is
2485
* @pre is_enabled() != true
2487
void ECA_CHAINSETUP::add_default_midi_device(void)
2489
if (midi_server_needed_rep == true &&
2490
midi_devices.size() == 0) {
2491
cparser_rep.interpret_object_option("-Md:" + default_midi_device());
2496
* Loads chainsetup options from file.
2498
* @pre is_enabled() != true
2500
void ECA_CHAINSETUP::load_from_file(const string& filename,
2501
vector<string>& opts) const throw(ECA_ERROR&)
2504
DBC_REQUIRE(is_enabled() != true);
2507
std::ifstream fin (filename.c_str());
2508
if (!fin) throw(ECA_ERROR("ECA_CHAINSETUP", "Couldn't open setup read file: \"" + filename + "\".", ECA_ERROR::retry));
2510
vector<string> options;
2512
while(getline(fin,temp)) {
2513
if (temp.size() > 0 && temp[0] == '#') {
2516
// FIXME: we should add quoting when saving the chainsetup or
2517
// give on quoting altogether...
2518
vector<string> words = kvu_string_to_tokens_quoted(temp);
2519
for(unsigned int n = 0; n < words.size(); n++) {
2520
ECA_LOG_MSG(ECA_LOGGER::system_objects, "Adding \"" + words[n] + "\" to options (loaded from \"" + filename + "\".");
2521
options.push_back(words[n]);
2526
opts = COMMAND_LINE::combine(options);
2529
void ECA_CHAINSETUP::save(void) throw(ECA_ERROR&)
2531
if (setup_filename_rep.empty() == true)
2532
setup_filename_rep = setup_name_rep + ".ecs";
2533
save_to_file(setup_filename_rep);
2536
void ECA_CHAINSETUP::save_to_file(const string& filename) throw(ECA_ERROR&)
2538
// make sure that all overrides are processed
2539
select_active_buffering_mode();
2541
std::ofstream fout (filename.c_str());
2543
cerr << "Going to throw an exception...\n";
2544
throw(ECA_ERROR("ECA_CHAINSETUP", "Couldn't open setup save file: \"" +
2545
filename + "\".", ECA_ERROR::retry));
2548
fout << "# ecasound chainsetup file" << endl;
2551
fout << "# general " << endl;
2552
fout << cparser_rep.general_options_to_string() << endl;
2555
string tmpstr = cparser_rep.midi_to_string();
2556
if (tmpstr.size() > 0) {
2557
fout << "# MIDI " << endl;
2558
fout << tmpstr << endl;
2562
fout << "# audio inputs " << endl;
2563
fout << cparser_rep.inputs_to_string() << endl;
2566
fout << "# audio outputs " << endl;
2567
fout << cparser_rep.outputs_to_string() << endl;
2570
tmpstr = cparser_rep.chains_to_string();
2571
if (tmpstr.size() > 0) {
2572
fout << "# chain operators and controllers " << endl;
2573
fout << tmpstr << endl;
2578
set_filename(filename);