1
// ------------------------------------------------------------------------
2
// eca-object-factory.cpp: Abstract factory for creating libecasound
4
// Copyright (C) 2000-2004 Kai Vehmanen
7
// eca-style-version: 3
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
// ------------------------------------------------------------------------
33
#include <sys/types.h>
37
#ifdef ECA_COMPILE_JACK
38
#include <jack/jack.h>
42
#include "kvu_locks.h"
43
#include <kvu_numtostr.h>
44
#include <kvu_message_item.h>
47
#include "audioio-loop.h"
49
#include "audiofx_ladspa.h"
50
#include "generic-controller.h"
51
#include "eca-static-object-maps.h"
52
#include "eca-object-map.h"
53
#include "eca-preset-map.h"
54
#include "eca-object-factory.h"
55
#include "eca-resources.h"
56
#include "eca-logger.h"
59
* Import std namespace.
66
* Initialize static member variables.
69
ECA_OBJECT_MAP* ECA_OBJECT_FACTORY::audio_io_rt_map_repp = 0;
70
ECA_OBJECT_MAP* ECA_OBJECT_FACTORY::audio_io_nonrt_map_repp = 0;
71
ECA_OBJECT_MAP* ECA_OBJECT_FACTORY::chain_operator_map_repp = 0;
72
ECA_OBJECT_MAP* ECA_OBJECT_FACTORY::ladspa_plugin_map_repp = 0;
73
ECA_OBJECT_MAP* ECA_OBJECT_FACTORY::ladspa_plugin_id_map_repp = 0;
74
ECA_PRESET_MAP* ECA_OBJECT_FACTORY::preset_map_repp = 0;
75
ECA_OBJECT_MAP* ECA_OBJECT_FACTORY::controller_map_repp = 0;
76
ECA_OBJECT_MAP* ECA_OBJECT_FACTORY::midi_device_map_repp = 0;
78
pthread_mutex_t ECA_OBJECT_FACTORY::lock_rep = PTHREAD_MUTEX_INITIALIZER;
81
* Definitions for static member functions.
85
* Returns an object map containing all registered
86
* realtime audio i/o object types.
88
* All stored objects are derived from AUDIO_IO_DEVICE.
90
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::audio_io_rt_map(void)
93
// Note! Below we use the Double-Checked Locking Pattern
94
// to protect against concurrent access
96
if (audio_io_rt_map_repp == 0) {
97
KVU_GUARD_LOCK guard(&ECA_OBJECT_FACTORY::lock_rep);
98
if (audio_io_rt_map_repp == 0) {
99
audio_io_rt_map_repp = new ECA_OBJECT_MAP();
100
ECA_STATIC_OBJECT_MAPS::register_audio_io_rt_objects(audio_io_rt_map_repp);
103
return *audio_io_rt_map_repp;
107
* Returns an object map containing all registered
108
* non-realtime audio i/o object types.
110
* All stored objects are derived from AUDIO_IO.
112
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::audio_io_nonrt_map(void)
114
if (audio_io_nonrt_map_repp == 0) {
115
KVU_GUARD_LOCK guard(&ECA_OBJECT_FACTORY::lock_rep);
116
if (audio_io_nonrt_map_repp == 0) {
117
audio_io_nonrt_map_repp = new ECA_OBJECT_MAP();
118
ECA_STATIC_OBJECT_MAPS::register_audio_io_nonrt_objects(audio_io_nonrt_map_repp);
121
return *audio_io_nonrt_map_repp;
125
* Returns an object map containing all registered
126
* chain operator object types.
128
* All stored objects are derived from CHAIN_OPERATOR.
130
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::chain_operator_map(void)
132
if (chain_operator_map_repp == 0) {
133
KVU_GUARD_LOCK guard(&ECA_OBJECT_FACTORY::lock_rep);
134
if (chain_operator_map_repp == 0) {
135
chain_operator_map_repp = new ECA_OBJECT_MAP();
136
ECA_STATIC_OBJECT_MAPS::register_chain_operator_objects(chain_operator_map_repp);
139
return *chain_operator_map_repp;
143
* Returns an object map containing all registered
144
* LADSPA plugin types.
147
* All stored objects are derived from EFFECT_LADSPA.
149
* @see ladspa_plugin_id_map()
151
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::ladspa_plugin_map(void)
153
if (ladspa_plugin_map_repp == 0) {
154
KVU_GUARD_LOCK guard(&ECA_OBJECT_FACTORY::lock_rep);
155
if (ladspa_plugin_map_repp == 0) {
156
ladspa_plugin_map_repp = new ECA_OBJECT_MAP();
157
ECA_STATIC_OBJECT_MAPS::register_ladspa_plugin_objects(ladspa_plugin_map_repp);
160
return *ladspa_plugin_map_repp;
164
* Returns an object map containing all registered
165
* LADSPA plugin types. Plugins are identified using
166
* their unique LADSPA id number.
168
* All stored objects are derived from EFFECT_LADSPA.
170
* @see ladspa_plugin_map()
172
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::ladspa_plugin_id_map(void)
174
if (ladspa_plugin_id_map_repp == 0) {
175
KVU_GUARD_LOCK guard(&ECA_OBJECT_FACTORY::lock_rep);
176
if (ladspa_plugin_id_map_repp == 0) {
177
ladspa_plugin_id_map_repp = new ECA_OBJECT_MAP();
178
ECA_STATIC_OBJECT_MAPS::register_ladspa_plugin_id_objects(ladspa_plugin_id_map_repp);
181
return *ladspa_plugin_id_map_repp;
185
* Returns an object map containing all registered
186
* chain operator preset object types.
188
* All stored objects are derived from PRESET.
190
ECA_PRESET_MAP& ECA_OBJECT_FACTORY::preset_map(void)
192
if (preset_map_repp == 0) {
193
KVU_GUARD_LOCK guard(&ECA_OBJECT_FACTORY::lock_rep);
194
if (preset_map_repp == 0) {
195
preset_map_repp = new ECA_PRESET_MAP();
196
ECA_STATIC_OBJECT_MAPS::register_preset_objects(preset_map_repp);
199
return *preset_map_repp;
203
* Returns an object map containing all registered
204
* controller object types.
206
* All stored objects are derived from GENERIC_CONTROLLER.
208
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::controller_map(void)
210
if (controller_map_repp == 0) {
211
KVU_GUARD_LOCK guard(&ECA_OBJECT_FACTORY::lock_rep);
212
if (controller_map_repp == 0) {
213
controller_map_repp = new ECA_OBJECT_MAP();
214
ECA_STATIC_OBJECT_MAPS::register_controller_objects(controller_map_repp);
217
return *controller_map_repp;
221
* Returns an object map containing all registered
225
* All stored objects are derived from MIDI_IO.
227
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::midi_device_map(void)
229
if (midi_device_map_repp == 0) {
230
KVU_GUARD_LOCK guard(&ECA_OBJECT_FACTORY::lock_rep);
231
if (midi_device_map_repp == 0) {
232
midi_device_map_repp = new ECA_OBJECT_MAP();
233
ECA_STATIC_OBJECT_MAPS::register_midi_device_objects(midi_device_map_repp);
236
return *midi_device_map_repp;
240
* Create a new audio object based on the formatted argument string.
242
* @param arg a formatted string describing an audio object, see ecasound
243
* manuals for detailed info
244
* @return the created object or 0 if an invalid format string was given
247
* @pre arg.empty() != true
249
AUDIO_IO* ECA_OBJECT_FACTORY::create_audio_object(const string& arg)
252
DBC_REQUIRE(arg.empty() != true);
255
string fname = kvu_get_argument_number(1, arg);
256
if (fname.find(".") != string::npos) {
257
fname = string(fname, fname.find_last_of("."), string::npos);
260
const AUDIO_IO* main_file = 0;
261
main_file = dynamic_cast<const AUDIO_IO*>(ECA_OBJECT_FACTORY::audio_io_rt_map().object_expr(fname));
262
if (main_file == 0) {
263
main_file = dynamic_cast<const AUDIO_IO*>(ECA_OBJECT_FACTORY::audio_io_nonrt_map().object_expr(fname));
266
AUDIO_IO* new_file = 0;
267
if (main_file != 0) {
268
new_file = main_file->new_expr();
269
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Object \"" + arg + "\" created, type \"" + new_file->name() + "\". Has " + kvu_numtostr(new_file->number_of_params()) + " parameter(s).");
270
for(int n = 0; n < new_file->number_of_params(); n++) {
271
new_file->set_parameter(n + 1, kvu_get_argument_number(n + 1, arg));
278
* Create a new MIDI-device object based on the formatted argument string.
280
* @param arg a formatted string describing a MIDI-device object, see ecasound
281
* manuals for detailed info
282
* @return the created object or 0 if an invalid format string was given
286
* arg.empty() != true
288
MIDI_IO* ECA_OBJECT_FACTORY::create_midi_device(const string& arg)
291
DBC_REQUIRE(arg.empty() != true);
294
string fname = kvu_get_argument_number(1, arg);
296
const MIDI_IO* device = 0;
297
device = dynamic_cast<const MIDI_IO*>(ECA_OBJECT_FACTORY::midi_device_map().object_expr(fname));
299
MIDI_IO* new_device = 0;
301
new_device = device->new_expr();
302
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Object \"" + arg + "\" created, type \"" + new_device->name() + "\". Has " + kvu_numtostr(new_device->number_of_params()) + " parameter(s).");
303
for(int n = 0; n < new_device->number_of_params(); n++) {
304
new_device->set_parameter(n + 1, kvu_get_argument_number(n + 1, arg));
311
* Create a new loop input object.
313
* @param arg a formatted string describing an loop object, see ecasound
314
* manuals for detailed info
315
* @return the created object or 0 if an invalid format string was given
318
* @pre argu.empty() != true
320
AUDIO_IO* ECA_OBJECT_FACTORY::create_loop_input(const string& argu,
321
map<int,LOOP_DEVICE*>* loop_map)
324
DBC_REQUIRE(argu.empty() != true);
328
string tname = kvu_get_argument_number(1, argu);
329
if (tname.find("loop") != string::npos) {
330
int id = atoi(kvu_get_argument_number(2, argu).c_str());
331
p = new LOOP_DEVICE(id);
332
if (loop_map->find(id) == loop_map->end()) {
345
* Create a new loop output object.
347
* @param arg a formatted string describing an loop object, see ecasound
348
* manuals for detailed info
349
* @return the created object or 0 if an invalid format string was given
352
* @pre argu.empty() != true
354
AUDIO_IO* ECA_OBJECT_FACTORY::create_loop_output(const string& argu,
355
map<int,LOOP_DEVICE*>* loop_map)
358
DBC_REQUIRE(argu.empty() != true);
362
string tname = kvu_get_argument_number(1, argu);
363
if (tname.find("loop") != string::npos) {
364
int id = atoi(kvu_get_argument_number(2, argu).c_str());
365
p = new LOOP_DEVICE(id);
366
if (loop_map->find(id) == loop_map->end()) {
372
p->register_output();
379
* Creates a new LADSPA plugin.
381
* @param arg a formatted string describing an LADSPA object, see ecasound
382
* manuals for detailed info
383
* @return the created object or 0 if an invalid format string was given
386
* @pre argu.size() > 0
387
* @pre argu[0] == '-'
389
CHAIN_OPERATOR* ECA_OBJECT_FACTORY::create_ladspa_plugin (const string& argu)
392
DBC_REQUIRE(argu.size() > 0);
393
DBC_REQUIRE(argu[0] == '-');
397
otemp.setprecision(3);
398
const CHAIN_OPERATOR* cop = 0;
399
string prefix = kvu_get_argument_prefix(argu);
400
if (prefix == "el" || prefix == "eli") {
401
string unique = kvu_get_argument_number(1, argu);
403
cop = dynamic_cast<const CHAIN_OPERATOR*>(ECA_OBJECT_FACTORY::ladspa_plugin_map().object(unique));
405
cop = dynamic_cast<const CHAIN_OPERATOR*>(ECA_OBJECT_FACTORY::ladspa_plugin_id_map().object(unique));
407
CHAIN_OPERATOR* new_cop = 0;
409
new_cop = dynamic_cast<CHAIN_OPERATOR*>(cop->new_expr());
411
ECA_LOG_MSG(ECA_LOGGER::user_objects,
412
"Creating LADSPA-plugin \"" + new_cop->name() + "\"");
414
otemp << "Setting parameters: ";
415
for(int n = 0; n < new_cop->number_of_params(); n++) {
416
new_cop->set_parameter(n + 1, atof(kvu_get_argument_number(n + 2, argu).c_str()));
417
otemp << new_cop->get_parameter_name(n + 1) << " = ";
418
otemp << new_cop->get_parameter(n + 1);
419
if (n + 1 < new_cop->number_of_params()) otemp << ", ";
421
ECA_LOG_MSG(ECA_LOGGER::user_objects, otemp.to_string());
424
ECA_LOG_MSG(ECA_LOGGER::info,
425
"ERROR: Unable to find LADSPA plugin \"" + unique + "\"");
434
* VST not currently actively supported due to licensing
439
* Creates a new VST1.0/2.0 plugin.
441
* Notes: VST support is currently not used
442
* because of licensing problems
443
* (distribution of VST-headers is not
446
CHAIN_OPERATOR* ECA_OBJECT_FACTORY::create_vst_plugin (const string& argu)
449
DBC_REQUIRE(argu.size() > 0);
450
DBC_REQUIRE(argu[0] == '-');
454
otemp.setprecision(3);
455
const CHAIN_OPERATOR* cop = 0;
456
string prefix = kvu_get_argument_prefix(argu);
458
cop = dynamic_cast<const CHAIN_OPERATOR*>(ECA_STATIC_OBJECT_MAPS::vst_plugin_map().object(prefix));
459
CHAIN_OPERATOR* new_cop = 0;
462
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Creating VST-plugin \"" + new_cop->name() + "\"");
463
otemp << "Setting parameters: ";
464
for(int n = 0; n < new_cop->number_of_params(); n++) {
465
new_cop->set_parameter(n + 1, atof(kvu_get_argument_number(n + 1, argu).c_str()));
466
otemp << new_cop->get_parameter_name(n + 1) << " = ";
467
otemp << new_cop->get_parameter(n + 1);
468
if (n + 1 < new_cop->number_of_params()) otemp << ", ";
470
ECA_LOG_MSG(ECA_LOGGER::user_objects, otemp.to_string());
474
#endif /* VST ifdef 0 */
477
* Creates a new chain operator object.
479
* @param arg a formatted string describing an chain operator object, see ecasound
480
* manuals for detailed info
481
* @return the created object or 0 if an invalid format string was given
484
* @pre argu.size() > 0
485
* @pre argu[0] == '-'
487
CHAIN_OPERATOR* ECA_OBJECT_FACTORY::create_chain_operator (const string& argu)
490
DBC_REQUIRE(argu.size() > 0);
491
DBC_REQUIRE(argu[0] == '-');
494
string prefix = kvu_get_argument_prefix(argu);
497
otemp.setprecision(3);
498
const CHAIN_OPERATOR* cop =
499
dynamic_cast<const CHAIN_OPERATOR*>(ECA_OBJECT_FACTORY::chain_operator_map().object(prefix));
500
CHAIN_OPERATOR* new_cop = 0;
502
new_cop = dynamic_cast<CHAIN_OPERATOR*>(cop->new_expr());
504
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Creating chain operator \"" +
505
new_cop->name() + "\"");
506
// otemp << "(eca-chainsetup) Adding effect " << new_cop->name();
507
otemp << "Setting parameters: ";
508
for(int n = 0; n < new_cop->number_of_params(); n++) {
509
new_cop->set_parameter(n + 1, atof(kvu_get_argument_number(n + 1, argu).c_str()));
510
otemp << new_cop->get_parameter_name(n + 1) << " = ";
511
otemp << new_cop->get_parameter(n +1);
512
if (n + 1 < new_cop->number_of_params()) otemp << ", ";
514
ECA_LOG_MSG(ECA_LOGGER::user_objects, otemp.to_string());
521
* Creates a new generic controller object.
523
* @param arg a formatted string describing an generic controller object, see ecasound
524
* manuals for detailed info
525
* @return the created object or 0 if an invalid format string was given
528
* @pre argu.size() > 0
529
* @pre argu[0] == '-'
531
GENERIC_CONTROLLER* ECA_OBJECT_FACTORY::create_controller (const string& argu)
534
DBC_REQUIRE(argu.size() > 0);
535
DBC_REQUIRE(argu[0] == '-');
538
if (argu.size() > 0 && argu[0] != '-') return 0;
539
string prefix = kvu_get_argument_prefix(argu);
541
const GENERIC_CONTROLLER* gcontroller =
542
dynamic_cast<const GENERIC_CONTROLLER*>(ECA_OBJECT_FACTORY::controller_map().object(prefix));
543
GENERIC_CONTROLLER* new_gcontroller = 0;
544
if (gcontroller != 0) {
545
new_gcontroller = gcontroller->new_expr();
546
if (new_gcontroller != 0) {
547
const CONTROLLER_SOURCE* csource = gcontroller->source_pointer();
548
CONTROLLER_SOURCE* new_csource = 0;
550
new_csource = csource->new_expr();
552
new_gcontroller->assign_source(new_csource);
554
ECA_LOG_MSG(ECA_LOGGER::user_objects, "Creating controller source \"" + new_gcontroller->name() + "\"");
557
otemp.setprecision(3);
558
otemp << "Setting parameters: ";
559
int numparams = new_gcontroller->number_of_params();
560
for(int n = 0; n < numparams; n++) {
561
new_gcontroller->set_parameter(n + 1, atof(kvu_get_argument_number(n + 1, argu).c_str()));
562
otemp << new_gcontroller->get_parameter_name(n + 1) << " = ";
563
otemp << new_gcontroller->get_parameter(n +1);
564
numparams = new_gcontroller->number_of_params(); // in case 'n_o_p()' varies
565
if (n + 1 < numparams) otemp << ", ";
567
ECA_LOG_MSG(ECA_LOGGER::user_objects, otemp.to_string());
569
return new_gcontroller;
576
* Returns a EOS-compatible string describing the default
577
* output device. This device is determined based on
578
* ecasoundrc settings, available resources,
579
* compile-time options, etc.
581
std::string ECA_OBJECT_FACTORY::probe_default_output_device(void)
583
ECA_RESOURCES ecaresources;
584
string default_output = ecaresources.resource("default-output");
585
bool output_selected = true;
587
if (default_output == "autodetect") {
589
output_selected = false;
591
#ifdef ECA_COMPILE_JACK
592
/* phase 1: check for JACK */
595
string cname = "ecasound-autodetect-" + kvu_numtostr(pid);
597
bool env_changed = false;
598
char* oldenv = getenv("JACK_NO_START_SERVER");
599
if (oldenv == NULL) {
601
setenv("JACK_NO_START_SERVER", "yes", 1);
604
jack_client_t *client = jack_client_new (cname.c_str());
606
jack_client_close(client);
608
default_output = "jack_alsa";
609
output_selected = true;
612
if (env_changed == true) {
613
unsetenv("JACK_NO_START_SERVER");
617
/* phase 2: check for ALSA support */
618
if (output_selected != true) {
619
const ECA_OBJECT *obj = ECA_OBJECT_FACTORY::audio_io_rt_map().object("alsa");
621
default_output = "alsa,default";
622
output_selected = true;
626
/* phase 3: check for OSS support */
627
if (output_selected != true) {
628
const ECA_OBJECT *obj = ECA_OBJECT_FACTORY::audio_io_rt_map().object("/dev/dsp");
630
default_output = "/dev/dsp";
631
output_selected = true;
635
/* phase 4: fallback to rtnull */
636
if (output_selected != true) {
637
ECA_LOG_MSG(ECA_LOGGER::info,
638
"WARNING: No default output available. Using 'rtnull' as a fallback.");
639
default_output = "rtnull";
643
return default_output;