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