pulling trunk
[ardour.git] / libs / ardour / globals.cc
1 /*
2     Copyright (C) 2000 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <locale.h>
27
28 #ifdef VST_SUPPORT
29 #include <fst.h>
30 #endif
31
32 #include <lrdf.h>
33
34 #include <pbd/error.h>
35 #include <pbd/strsplit.h>
36
37 #include <midi++/port.h>
38 #include <midi++/port_request.h>
39 #include <midi++/manager.h>
40 #include <midi++/mmc.h>
41
42 #include <ardour/ardour.h>
43 #include <ardour/audio_library.h>
44 #include <ardour/configuration.h>
45 #include <ardour/plugin_manager.h>
46 #include <ardour/source.h>
47 #include <ardour/utils.h>
48 #include <ardour/session.h>
49 #include <ardour/control_protocol_manager.h>
50
51 #ifdef HAVE_LIBLO
52 #include <ardour/osc.h>
53 #endif
54
55 #include <ardour/mix.h>
56
57 #if defined (__APPLE__)
58        #include <Carbon/Carbon.h> // For Gestalt
59 #endif
60        
61 #include "i18n.h"
62
63 ARDOUR::Configuration* ARDOUR::Config = 0;
64 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
65
66 #ifdef HAVE_LIBLO
67 ARDOUR::OSC* ARDOUR::osc = 0;
68 #endif
69
70 using namespace ARDOUR;
71 using namespace std;
72
73 MIDI::Port *default_mmc_port = 0;
74 MIDI::Port *default_mtc_port = 0;
75 MIDI::Port *default_midi_port = 0;
76
77 Change ARDOUR::StartChanged = ARDOUR::new_change ();
78 Change ARDOUR::LengthChanged = ARDOUR::new_change ();
79 Change ARDOUR::PositionChanged = ARDOUR::new_change ();
80 Change ARDOUR::NameChanged = ARDOUR::new_change ();
81 Change ARDOUR::BoundsChanged = Change (0); // see init(), below
82
83 #ifdef HAVE_LIBLO
84 static int
85 setup_osc ()
86 {
87         /* no real cost to creating this object, and it avoids
88            conditionals anywhere that uses it 
89         */
90         
91         osc = new OSC (Config->get_osc_port());
92         
93         if (Config->get_use_osc ()) {
94                 return osc->start ();
95         } else {
96                 return 0;
97         }
98 }
99 #endif
100
101 static int 
102 setup_midi ()
103 {
104         std::map<string,Configuration::MidiPortDescriptor*>::iterator i;
105         int nports;
106
107         if ((nports = Config->midi_ports.size()) == 0) {
108                 warning << _("no MIDI ports specified: no MMC or MTC control possible") << endmsg;
109                 return 0;
110         }
111
112         for (i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) {
113                 Configuration::MidiPortDescriptor* port_descriptor;
114
115                 port_descriptor = (*i).second;
116
117                 MIDI::PortRequest request (port_descriptor->device, 
118                                            port_descriptor->tag, 
119                                            port_descriptor->mode, 
120                                            port_descriptor->type);
121
122                 if (request.status != MIDI::PortRequest::OK) {
123                         error << string_compose(_("MIDI port specifications for \"%1\" are not understandable."), port_descriptor->tag) << endmsg;
124                         continue;
125                 }
126                 
127                 MIDI::Manager::instance()->add_port (request);
128         }
129
130         if (nports > 1) {
131
132                 /* More than one port, so try using specific names for each port */
133
134                 map<string,Configuration::MidiPortDescriptor *>::iterator i;
135
136                 if (Config->get_mmc_port_name() != N_("default")) {
137                         default_mmc_port =  MIDI::Manager::instance()->port (Config->get_mmc_port_name());
138                 } 
139
140                 if (Config->get_mtc_port_name() != N_("default")) {
141                         default_mtc_port =  MIDI::Manager::instance()->port (Config->get_mtc_port_name());
142                 } 
143
144                 if (Config->get_midi_port_name() != N_("default")) {
145                         default_midi_port =  MIDI::Manager::instance()->port (Config->get_midi_port_name());
146                 } 
147                 
148                 /* If that didn't work, just use the first listed port */
149
150                 if (default_mmc_port == 0) {
151                         default_mmc_port = MIDI::Manager::instance()->port (0);
152                 }
153
154                 if (default_mtc_port == 0) {
155                         default_mtc_port = MIDI::Manager::instance()->port (0);
156                 }
157
158                 if (default_midi_port == 0) {
159                         default_midi_port = MIDI::Manager::instance()->port (0);
160                 }
161                 
162         } else {
163
164                 /* Only one port described, so use it for both MTC and MMC */
165
166                 default_mmc_port = MIDI::Manager::instance()->port (0);
167                 default_mtc_port = default_mmc_port;
168                 default_midi_port = default_mmc_port;
169         }
170
171         if (default_mmc_port == 0) {
172                 warning << string_compose (_("No MMC control (MIDI port \"%1\" not available)"), Config->get_mmc_port_name()) 
173                         << endmsg;
174                 return 0;
175         } 
176
177         if (default_mtc_port == 0) {
178                 warning << string_compose (_("No MTC support (MIDI port \"%1\" not available)"), Config->get_mtc_port_name()) 
179                         << endmsg;
180         }
181
182         if (default_midi_port == 0) {
183                 warning << string_compose (_("No MIDI parameter support (MIDI port \"%1\" not available)"), Config->get_midi_port_name()) 
184                         << endmsg;
185         }
186
187         return 0;
188 }
189
190 int
191 ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization, void (*sighandler)(int,siginfo_t*,void*))
192 {
193         bool generic_mix_functions = true;
194
195         (void) bindtextdomain(PACKAGE, LOCALEDIR);
196
197         Config = new Configuration;
198
199         if (Config->load_state ()) {
200                 return -1;
201         }
202
203         Config->set_use_vst (use_vst);
204
205         if (setup_midi ()) {
206                 return -1;
207         }
208     
209 #ifdef HAVE_LIBLO
210         if (setup_osc ()) {
211                 return -1;
212         }
213 #endif
214
215 #ifdef VST_SUPPORT
216         if (Config->get_use_vst() && fst_init (sighandler)) {
217                 return -1;
218         }
219 #endif
220
221         if (try_optimization) {
222
223 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
224         
225                 unsigned int use_sse = 0;
226
227 #ifndef USE_X86_64_ASM
228                 asm volatile (
229                                  "mov $1, %%eax\n"
230                                  "pushl %%ebx\n"
231                                  "cpuid\n"
232                                  "popl %%ebx\n"
233                                  "andl $33554432, %%edx\n"
234                                  "movl %%edx, %0\n"
235                              : "=m" (use_sse)
236                              : 
237                          : "%eax", "%ecx", "%edx", "memory");
238 #else
239
240                 asm volatile (
241                                  "movq $1, %%rax\n"
242                                  "pushq %%rbx\n"
243                                  "cpuid\n"
244                                  "popq %%rbx\n"
245                                  "andq $33554432, %%rdx\n"
246                                  "movq %%rdx, %0\n"
247                              : "=m" (use_sse)
248                              : 
249                          : "%rax", "%rcx", "%rdx", "memory");
250
251 #endif /* USE_X86_64_ASM */
252                 
253                 if (use_sse) {
254                         cerr << "Enabling SSE optimized routines" << endl;
255         
256                         // SSE SET
257                         Session::compute_peak                   = x86_sse_compute_peak;
258                         Session::apply_gain_to_buffer   = x86_sse_apply_gain_to_buffer;
259                         Session::mix_buffers_with_gain  = x86_sse_mix_buffers_with_gain;
260                         Session::mix_buffers_no_gain    = x86_sse_mix_buffers_no_gain;
261
262                         generic_mix_functions = false;
263
264                 }
265
266 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
267                 long sysVersion = 0;
268
269                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
270                         sysVersion = 0;
271
272                 if (sysVersion >= 0x00001040) { // Tiger at least
273                         Session::compute_peak           = veclib_compute_peak;
274                         Session::apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
275                         Session::mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
276                         Session::mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
277
278                         generic_mix_functions = false;
279
280                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
281                 }
282 #endif
283         }
284
285         if (generic_mix_functions) {
286
287                 Session::compute_peak                   = compute_peak;
288                 Session::apply_gain_to_buffer   = apply_gain_to_buffer;
289                 Session::mix_buffers_with_gain  = mix_buffers_with_gain;
290                 Session::mix_buffers_no_gain    = mix_buffers_no_gain;
291                 
292                 info << "No H/W specific optimizations in use" << endmsg;
293         }
294         
295         lrdf_init();
296         Library = new AudioLibrary;
297
298         /* singleton - first object is "it" */
299         new PluginManager (engine);
300         
301         /* singleton - first object is "it" */
302         new ControlProtocolManager ();
303         ControlProtocolManager::instance().discover_control_protocols (Session::control_protocol_path());
304
305         XMLNode* node;
306         if ((node = Config->control_protocol_state()) != 0) {
307                 ControlProtocolManager::instance().set_state (*node);
308         }
309         
310         BoundsChanged = Change (StartChanged|PositionChanged|LengthChanged);
311
312         return 0;
313 }
314
315 int
316 ARDOUR::cleanup ()
317 {
318         delete Library;
319         lrdf_cleanup ();
320         delete &ControlProtocolManager::instance();
321         return 0;
322 }
323
324 ARDOUR::id_t
325 ARDOUR::new_id ()
326 {
327         return get_uid();
328 }
329
330 ARDOUR::Change
331 ARDOUR::new_change ()
332 {
333         Change c;
334         static uint32_t change_bit = 1;
335
336         /* catch out-of-range */
337         if (!change_bit)
338         {
339                 fatal << _("programming error: ")
340                         << "change_bit out of range in ARDOUR::new_change()"
341                         << endmsg;
342                 /*NOTREACHED*/
343         }
344
345         c = Change (change_bit);
346         change_bit <<= 1;       // if it shifts too far, change_bit == 0
347
348         return c;
349 }
350
351 string
352 ARDOUR::get_user_ardour_path ()
353 {
354         string path;
355         char* envvar;
356         
357         if ((envvar = getenv ("HOME")) == 0 || strlen (envvar) == 0) {
358                 return "/";
359         }
360                 
361         path = envvar;
362         path += "/.ardour2/";
363
364         /* create it if necessary */
365
366         mkdir (path.c_str (), 0755);
367
368         return path;
369 }
370
371 string
372 ARDOUR::get_system_data_path ()
373 {
374         string path;
375
376         path += DATA_DIR;
377         path += "/ardour2/";
378         
379         return path;
380 }
381
382 string
383 ARDOUR::get_system_module_path ()
384 {
385         string path;
386
387         path += MODULE_DIR;
388         path += "/ardour2/";
389         
390         return path;
391 }
392
393 static string
394 find_file (string name, string dir, string subdir = "")
395 {
396         string path;
397         char* envvar = getenv("ARDOUR_PATH");
398
399         /* 1st attempt: any directory in ARDOUR_PATH */
400         
401         if (envvar != 0) {
402
403                 vector<string> split_path;
404         
405                 split (envvar, split_path, ':');
406                 
407                 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
408                         path = *i;
409                         path += "/" + name;
410                         if (access (path.c_str(), R_OK) == 0) {
411                                 // cerr << "Using file " << path << " found in ARDOUR_PATH." << endl;
412                                 return path;
413                         }
414                 }
415         }
416
417         /* 2nd attempt: ~/.ardour/ */
418
419         path = get_user_ardour_path();
420                 
421         if (subdir.length()) {
422                 path += subdir + "/";
423         }
424                 
425         path += name;
426         if (access (path.c_str(), R_OK) == 0) {
427                 return path;
428         }
429
430         /* 3rd attempt: dir/... */
431         
432         path = dir;
433         path += "/ardour2/";
434         
435         if (subdir.length()) {
436                 path += subdir + "/";
437         }
438         
439         path += name;
440         
441         if (access (path.c_str(), R_OK) == 0) {
442                 return path;
443         }
444
445         return "";
446 }
447
448 string
449 ARDOUR::find_config_file (string name)
450 {
451         char* envvar;
452
453         if ((envvar = getenv("ARDOUR_CONFIG_PATH")) == 0) {
454                 envvar = CONFIG_DIR;
455         }
456
457         return find_file (name, envvar);
458 }
459
460 string
461 ARDOUR::find_data_file (string name, string subdir)
462 {
463         char* envvar;
464         if ((envvar = getenv("ARDOUR_DATA_PATH")) == 0) {
465                 envvar = DATA_DIR;
466         }
467
468         return find_file (name, envvar, subdir);
469 }
470
471 ARDOUR::LocaleGuard::LocaleGuard (const char* str)
472 {
473         old = strdup (setlocale (LC_NUMERIC, NULL));
474         if (strcmp (old, str)) {
475                 setlocale (LC_NUMERIC, str);
476         } 
477 }
478
479 ARDOUR::LocaleGuard::~LocaleGuard ()
480 {
481         setlocale (LC_NUMERIC, old);
482         free ((char*)old);
483 }
484
485 ARDOUR::OverlapType
486 ARDOUR::coverage (jack_nframes_t sa, jack_nframes_t ea, 
487                   jack_nframes_t sb, jack_nframes_t eb)
488 {
489         /* OverlapType returned reflects how the second (B)
490            range overlaps the first (A).
491
492            The diagrams show various relative placements
493            of A and B for each OverlapType.
494
495            Notes:
496               Internal: the start points cannot coincide
497               External: the start and end points can coincide
498               Start: end points can coincide
499               End: start points can coincide
500
501            XXX Logically, Internal should disallow end
502            point equality.
503         */
504
505         /*
506              |--------------------|   A
507                   |------|            B
508                 |-----------------|   B
509
510
511              "B is internal to A"               
512
513         */
514 #ifdef OLD_COVERAGE
515         if ((sb >= sa) && (eb <= ea)) {
516 #else
517         if ((sb > sa) && (eb <= ea)) {
518 #endif
519                 return OverlapInternal;
520         }
521
522         /*
523              |--------------------|   A
524            ----|                      B
525            -----------------------|   B
526            --|                        B
527            
528              "B overlaps the start of A"
529
530         */
531
532         if ((eb >= sa) && (eb <= ea)) {
533                 return OverlapStart;
534         }
535         /* 
536              |---------------------|  A
537                    |----------------- B
538              |----------------------- B    
539                                    |- B
540
541             "B overlaps the end of A"                              
542
543         */
544         if ((sb >= sa) && (sb <= ea)) {
545                 return OverlapEnd;
546         }
547         /*
548              |--------------------|     A
549            --------------------------  B   
550              |-----------------------  B
551             ----------------------|    B
552              |--------------------|    B
553
554
555            "B overlaps all of A"
556         */
557         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
558                 return OverlapExternal;
559         }
560
561         return OverlapNone;
562 }
563
564 /* not sure where to put these */
565
566 std::istream& operator>>(std::istream& o, HeaderFormat& hf) {
567         int val;
568         o >> val;
569         hf = (HeaderFormat) val;
570         return o;
571 }
572
573 std::istream& operator>>(std::istream& o, SampleFormat& sf) {
574         int val;
575         o >> val;
576         sf = (SampleFormat) val;
577         return o;
578 }