~ubuntu-branches/ubuntu/jaunty/ecasound2.2/jaunty

« back to all changes in this revision

Viewing changes to libecasound/eca-object-factory.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Junichi Uekawa
  • Date: 2005-04-14 09:15:48 UTC
  • Revision ID: james.westby@ubuntu.com-20050414091548-o7kgb47z0tcunh0s
Tags: upstream-2.4.1
ImportĀ upstreamĀ versionĀ 2.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ------------------------------------------------------------------------
 
2
// eca-object-factory.cpp: Abstract factory for creating libecasound 
 
3
//                         objects.
 
4
// Copyright (C) 2000-2004 Kai Vehmanen
 
5
//
 
6
// Attributes:
 
7
//     eca-style-version: 3
 
8
//
 
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.
 
13
// 
 
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.
 
18
// 
 
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
// ------------------------------------------------------------------------
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include <list>
 
29
#include <map>
 
30
#include <string>
 
31
#include <pthread.h>
 
32
 
 
33
#include <sys/types.h>
 
34
#include <unistd.h>
 
35
#include <stdlib.h>
 
36
 
 
37
#ifdef ECA_COMPILE_JACK
 
38
#include <jack/jack.h>
 
39
#endif
 
40
 
 
41
#include <kvu_dbc.h>
 
42
#include "kvu_locks.h"
 
43
#include <kvu_numtostr.h>
 
44
#include <kvu_message_item.h>
 
45
 
 
46
#include "audioio.h"
 
47
#include "audioio-loop.h"
 
48
#include "midiio.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"
 
57
 
 
58
/**
 
59
 * Import std namespace.
 
60
 */
 
61
using std::list;
 
62
using std::map;
 
63
using std::string;
 
64
 
 
65
/**
 
66
 * Initialize static member variables.
 
67
 */
 
68
 
 
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;
 
77
 
 
78
pthread_mutex_t ECA_OBJECT_FACTORY::lock_rep = PTHREAD_MUTEX_INITIALIZER;
 
79
 
 
80
/**
 
81
 * Definitions for static member functions.
 
82
 */
 
83
 
 
84
/**
 
85
 * Returns an object map containing all registered
 
86
 * realtime audio i/o object types.
 
87
 *
 
88
 * All stored objects are derived from AUDIO_IO_DEVICE.
 
89
 */
 
90
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::audio_io_rt_map(void) 
 
91
{
 
92
  //
 
93
  // Note! Below we use the Double-Checked Locking Pattern
 
94
  //       to protect against concurrent access
 
95
 
 
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);
 
101
    }
 
102
  }
 
103
  return *audio_io_rt_map_repp;
 
104
}
 
105
 
 
106
/**
 
107
 * Returns an object map containing all registered
 
108
 * non-realtime audio i/o object types.
 
109
 *
 
110
 * All stored objects are derived from AUDIO_IO.
 
111
 */
 
112
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::audio_io_nonrt_map(void) 
 
113
{
 
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);
 
119
    }
 
120
  }
 
121
  return *audio_io_nonrt_map_repp;
 
122
}
 
123
 
 
124
/**
 
125
 * Returns an object map containing all registered
 
126
 * chain operator object types.
 
127
 *
 
128
 * All stored objects are derived from CHAIN_OPERATOR.
 
129
 */
 
130
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::chain_operator_map(void) 
 
131
{
 
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);
 
137
    }
 
138
  }
 
139
  return *chain_operator_map_repp;
 
140
}
 
141
 
 
142
/**
 
143
 * Returns an object map containing all registered
 
144
 * LADSPA plugin types.
 
145
 * 
 
146
 *
 
147
 * All stored objects are derived from EFFECT_LADSPA.
 
148
 *
 
149
 * @see ladspa_plugin_id_map()
 
150
 */
 
151
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::ladspa_plugin_map(void) 
 
152
{
 
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);
 
158
    }
 
159
  }
 
160
  return *ladspa_plugin_map_repp;
 
161
}
 
162
 
 
163
/**
 
164
 * Returns an object map containing all registered
 
165
 * LADSPA plugin types. Plugins are identified using
 
166
 * their unique LADSPA id number.
 
167
 * 
 
168
 * All stored objects are derived from EFFECT_LADSPA.
 
169
 *
 
170
 * @see ladspa_plugin_map()
 
171
 */
 
172
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::ladspa_plugin_id_map(void) 
 
173
{
 
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);
 
179
    }
 
180
  }
 
181
  return *ladspa_plugin_id_map_repp;
 
182
}
 
183
 
 
184
/**
 
185
 * Returns an object map containing all registered
 
186
 * chain operator preset object types.
 
187
 *
 
188
 * All stored objects are derived from PRESET.
 
189
 */
 
190
ECA_PRESET_MAP& ECA_OBJECT_FACTORY::preset_map(void) 
 
191
{
 
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);
 
197
    }
 
198
  }
 
199
  return *preset_map_repp;
 
200
}
 
201
 
 
202
/**
 
203
 * Returns an object map containing all registered
 
204
 * controller object types.
 
205
 *
 
206
 * All stored objects are derived from GENERIC_CONTROLLER.
 
207
 */
 
208
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::controller_map(void) 
 
209
{
 
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);
 
215
    }
 
216
  }
 
217
  return *controller_map_repp;
 
218
}
 
219
 
 
220
/**
 
221
 * Returns an object map containing all registered
 
222
 * MIDI-device types.
 
223
 *
 
224
 *
 
225
 * All stored objects are derived from MIDI_IO.
 
226
 */
 
227
ECA_OBJECT_MAP& ECA_OBJECT_FACTORY::midi_device_map(void) 
 
228
{
 
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);
 
234
    }
 
235
  }
 
236
  return *midi_device_map_repp;
 
237
}
 
238
 
 
239
/**
 
240
 * Create a new audio object based on the formatted argument string.
 
241
 *
 
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 
 
245
 *         as the argument
 
246
 *
 
247
 * @pre arg.empty() != true
 
248
 */
 
249
AUDIO_IO* ECA_OBJECT_FACTORY::create_audio_object(const string& arg)
 
250
{
 
251
  // --
 
252
  DBC_REQUIRE(arg.empty() != true);
 
253
  // --
 
254
 
 
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);
 
258
  }
 
259
 
 
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));
 
264
  }
 
265
 
 
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));
 
272
    }
 
273
  }
 
274
  return new_file;
 
275
}
 
276
 
 
277
/**
 
278
 * Create a new MIDI-device object based on the formatted argument string.
 
279
 *
 
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 
 
283
 *         as the argument
 
284
 *
 
285
 * require:
 
286
 *  arg.empty() != true
 
287
 */
 
288
MIDI_IO* ECA_OBJECT_FACTORY::create_midi_device(const string& arg)
 
289
{
 
290
  // --------
 
291
  DBC_REQUIRE(arg.empty() != true);
 
292
  // --------
 
293
 
 
294
  string fname = kvu_get_argument_number(1, arg);
 
295
 
 
296
  const MIDI_IO* device = 0;
 
297
  device = dynamic_cast<const MIDI_IO*>(ECA_OBJECT_FACTORY::midi_device_map().object_expr(fname));
 
298
 
 
299
  MIDI_IO* new_device = 0;
 
300
  if (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));
 
305
    }
 
306
  }
 
307
  return new_device;
 
308
}
 
309
 
 
310
/**
 
311
 * Create a new loop input object.
 
312
 *
 
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 
 
316
 *         as the argument
 
317
 *
 
318
 * @pre argu.empty() != true
 
319
 */
 
320
AUDIO_IO* ECA_OBJECT_FACTORY::create_loop_input(const string& argu,
 
321
                                                map<int,LOOP_DEVICE*>* loop_map)
 
322
{
 
323
  // --------
 
324
  DBC_REQUIRE(argu.empty() != true);
 
325
  // --------
 
326
 
 
327
  LOOP_DEVICE* p = 0;
 
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()) { 
 
333
      (*loop_map)[id] = p;
 
334
    }
 
335
    else
 
336
      p = (*loop_map)[id];
 
337
 
 
338
    p->register_input();
 
339
  }
 
340
  
 
341
  return p;
 
342
}
 
343
 
 
344
/**
 
345
 * Create a new loop output object.
 
346
 *
 
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 
 
350
 *         as the argument
 
351
 *
 
352
 * @pre argu.empty() != true
 
353
 */
 
354
AUDIO_IO* ECA_OBJECT_FACTORY::create_loop_output(const string& argu,
 
355
                                                 map<int,LOOP_DEVICE*>* loop_map)
 
356
{
 
357
  // --------
 
358
  DBC_REQUIRE(argu.empty() != true);
 
359
  // --------
 
360
 
 
361
  LOOP_DEVICE* p = 0;
 
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()) { 
 
367
      (*loop_map)[id] = p;
 
368
    }
 
369
    else
 
370
      p = (*loop_map)[id];
 
371
 
 
372
    p->register_output();
 
373
  }
 
374
  
 
375
  return p;
 
376
}
 
377
 
 
378
/**
 
379
 * Creates a new LADSPA plugin.
 
380
 *
 
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 
 
384
 *         as the argument
 
385
 *
 
386
 * @pre argu.size() > 0
 
387
 * @pre argu[0] == '-'
 
388
 */
 
389
CHAIN_OPERATOR* ECA_OBJECT_FACTORY::create_ladspa_plugin (const string& argu)
 
390
{
 
391
  // --------
 
392
  DBC_REQUIRE(argu.size() > 0);
 
393
  DBC_REQUIRE(argu[0] == '-');
 
394
  // --------
 
395
 
 
396
  MESSAGE_ITEM otemp;
 
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);
 
402
    if (prefix == "el") 
 
403
      cop = dynamic_cast<const CHAIN_OPERATOR*>(ECA_OBJECT_FACTORY::ladspa_plugin_map().object(unique));
 
404
    else 
 
405
      cop = dynamic_cast<const CHAIN_OPERATOR*>(ECA_OBJECT_FACTORY::ladspa_plugin_id_map().object(unique));
 
406
 
 
407
    CHAIN_OPERATOR* new_cop = 0;
 
408
    if (cop != 0) {
 
409
      new_cop = dynamic_cast<CHAIN_OPERATOR*>(cop->new_expr());
 
410
 
 
411
      ECA_LOG_MSG(ECA_LOGGER::user_objects, 
 
412
                  "Creating LADSPA-plugin \"" + new_cop->name() + "\"");
 
413
 
 
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 << ", ";
 
420
      }
 
421
      ECA_LOG_MSG(ECA_LOGGER::user_objects, otemp.to_string());
 
422
    }
 
423
    else {
 
424
      ECA_LOG_MSG(ECA_LOGGER::info, 
 
425
                  "ERROR: Unable to find LADSPA plugin \"" + unique + "\"");
 
426
 
 
427
    }
 
428
    return new_cop;
 
429
  }
 
430
  return 0;
 
431
}
 
432
 
 
433
/**
 
434
 * VST not currently actively supported due to licensing
 
435
 * issues.
 
436
 */
 
437
#if 0
 
438
/**
 
439
 * Creates a new VST1.0/2.0 plugin.
 
440
 *
 
441
 * Notes: VST support is currently not used 
 
442
 *        because of licensing problems 
 
443
 *        (distribution of VST-headers is not
 
444
 *        allowed).
 
445
 */
 
446
CHAIN_OPERATOR* ECA_OBJECT_FACTORY::create_vst_plugin (const string& argu)
 
447
{
 
448
  // --------
 
449
  DBC_REQUIRE(argu.size() > 0);
 
450
  DBC_REQUIRE(argu[0] == '-');
 
451
  // --------
 
452
 
 
453
  MESSAGE_ITEM otemp;
 
454
  otemp.setprecision(3);
 
455
  const CHAIN_OPERATOR* cop = 0;
 
456
  string prefix = kvu_get_argument_prefix(argu);
 
457
 
 
458
  cop = dynamic_cast<const CHAIN_OPERATOR*>(ECA_STATIC_OBJECT_MAPS::vst_plugin_map().object(prefix));
 
459
  CHAIN_OPERATOR* new_cop = 0;
 
460
  if (cop != 0) {
 
461
    
 
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 << ", ";
 
469
    }
 
470
    ECA_LOG_MSG(ECA_LOGGER::user_objects, otemp.to_string());
 
471
  }
 
472
  return new_cop;
 
473
}
 
474
#endif /* VST ifdef 0 */
 
475
 
 
476
/**
 
477
 * Creates a new chain operator object.
 
478
 *
 
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 
 
482
 *         as the argument
 
483
 *
 
484
 * @pre argu.size() > 0
 
485
 * @pre argu[0] == '-'
 
486
 */
 
487
CHAIN_OPERATOR* ECA_OBJECT_FACTORY::create_chain_operator (const string& argu)
 
488
{
 
489
  // --------
 
490
  DBC_REQUIRE(argu.size() > 0);
 
491
  DBC_REQUIRE(argu[0] == '-');
 
492
  // --------
 
493
 
 
494
  string prefix = kvu_get_argument_prefix(argu);
 
495
 
 
496
  MESSAGE_ITEM otemp;
 
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;
 
501
  if (cop != 0) {
 
502
    new_cop = dynamic_cast<CHAIN_OPERATOR*>(cop->new_expr());
 
503
 
 
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 << ", ";
 
513
    }
 
514
    ECA_LOG_MSG(ECA_LOGGER::user_objects, otemp.to_string());
 
515
    return new_cop;
 
516
  }
 
517
  return 0;
 
518
}
 
519
 
 
520
/**
 
521
 * Creates a new generic controller object.
 
522
 *
 
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 
 
526
 *         as the argument
 
527
 *
 
528
 * @pre argu.size() > 0
 
529
 * @pre argu[0] == '-'
 
530
 */
 
531
GENERIC_CONTROLLER* ECA_OBJECT_FACTORY::create_controller (const string& argu)
 
532
{
 
533
  // --------
 
534
  DBC_REQUIRE(argu.size() > 0);
 
535
  DBC_REQUIRE(argu[0] == '-');
 
536
  // --------
 
537
 
 
538
  if (argu.size() > 0 && argu[0] != '-') return 0;
 
539
  string prefix = kvu_get_argument_prefix(argu);
 
540
 
 
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;
 
549
      if (csource != 0) {
 
550
        new_csource = csource->new_expr();
 
551
      }
 
552
      new_gcontroller->assign_source(new_csource);
 
553
 
 
554
      ECA_LOG_MSG(ECA_LOGGER::user_objects, "Creating controller source \"" +  new_gcontroller->name() + "\"");
 
555
 
 
556
      MESSAGE_ITEM otemp;
 
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 << ", ";
 
566
      }
 
567
      ECA_LOG_MSG(ECA_LOGGER::user_objects, otemp.to_string());
 
568
 
 
569
      return new_gcontroller;
 
570
    }
 
571
  }
 
572
  return 0;
 
573
}
 
574
 
 
575
/**
 
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.
 
580
 */
 
581
std::string ECA_OBJECT_FACTORY::probe_default_output_device(void)
 
582
{
 
583
    ECA_RESOURCES ecaresources;
 
584
    string default_output = ecaresources.resource("default-output");
 
585
    bool output_selected = true;
 
586
 
 
587
    if (default_output == "autodetect") {
 
588
      
 
589
      output_selected = false;
 
590
 
 
591
#ifdef ECA_COMPILE_JACK
 
592
      /* phase 1: check for JACK */
 
593
 
 
594
      int pid = getpid();
 
595
      string cname = "ecasound-autodetect-" + kvu_numtostr(pid);
 
596
 
 
597
      bool env_changed = false;
 
598
      char* oldenv = getenv("JACK_NO_START_SERVER");
 
599
      if (oldenv == NULL) {
 
600
        env_changed = true;
 
601
        setenv("JACK_NO_START_SERVER", "yes", 1);
 
602
      }
 
603
      
 
604
      jack_client_t *client = jack_client_new (cname.c_str());
 
605
      if (client != 0) {
 
606
        jack_client_close(client);
 
607
        
 
608
        default_output = "jack_alsa";
 
609
        output_selected = true;
 
610
      }
 
611
      
 
612
      if (env_changed == true) {
 
613
        unsetenv("JACK_NO_START_SERVER");
 
614
      }
 
615
#endif
 
616
      
 
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");
 
620
        if (obj != 0) {
 
621
          default_output = "alsa,default";
 
622
          output_selected = true;
 
623
        }
 
624
      }
 
625
      
 
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");
 
629
        if (obj != 0) {
 
630
          default_output = "/dev/dsp";
 
631
          output_selected = true;
 
632
        }
 
633
      }
 
634
      
 
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";
 
640
      }
 
641
    }
 
642
 
 
643
    return default_output;
 
644
}