moved OSC into libardour
[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         /* XXX catch out-of-range */
327
328         c = Change (change_bit);
329         change_bit <<= 1;
330
331         return c;
332 }
333
334 string
335 ARDOUR::get_user_ardour_path ()
336 {
337         string path;
338         char* envvar;
339         
340         if ((envvar = getenv ("HOME")) == 0 || strlen (envvar) == 0) {
341                 return "/";
342         }
343                 
344         path = envvar;
345         path += "/.ardour2/";
346
347         /* create it if necessary */
348
349         mkdir (path.c_str (), 0755);
350
351         return path;
352 }
353
354 string
355 ARDOUR::get_system_data_path ()
356 {
357         string path;
358
359         path += DATA_DIR;
360         path += "/ardour2/";
361         
362         return path;
363 }
364
365 string
366 ARDOUR::get_system_module_path ()
367 {
368         string path;
369
370         path += MODULE_DIR;
371         path += "/ardour2/";
372         
373         return path;
374 }
375
376 static string
377 find_file (string name, string dir, string subdir = "")
378 {
379         string path;
380         char* envvar = getenv("ARDOUR_PATH");
381
382         /* 1st attempt: any directory in ARDOUR_PATH */
383         
384         if (envvar != 0) {
385
386                 vector<string> split_path;
387         
388                 split (envvar, split_path, ':');
389                 
390                 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
391                         path = *i;
392                         path += "/" + name;
393                         if (access (path.c_str(), R_OK) == 0) {
394                                 // cerr << "Using file " << path << " found in ARDOUR_PATH." << endl;
395                                 return path;
396                         }
397                 }
398         }
399
400         /* 2nd attempt: ~/.ardour/ */
401
402         path = get_user_ardour_path();
403                 
404         if (subdir.length()) {
405                 path += subdir + "/";
406         }
407                 
408         path += name;
409         if (access (path.c_str(), R_OK) == 0) {
410                 return path;
411         }
412
413         /* 3rd attempt: dir/... */
414         
415         path = dir;
416         path += "/ardour2/";
417         
418         if (subdir.length()) {
419                 path += subdir + "/";
420         }
421         
422         path += name;
423         
424         if (access (path.c_str(), R_OK) == 0) {
425                 return path;
426         }
427
428         return "";
429 }
430
431 string
432 ARDOUR::find_config_file (string name)
433 {
434         char* envvar;
435
436         if ((envvar = getenv("ARDOUR_CONFIG_PATH")) == 0) {
437                 envvar = CONFIG_DIR;
438         }
439
440         return find_file (name, envvar);
441 }
442
443 string
444 ARDOUR::find_data_file (string name, string subdir)
445 {
446         char* envvar;
447         if ((envvar = getenv("ARDOUR_DATA_PATH")) == 0) {
448                 envvar = DATA_DIR;
449         }
450
451         return find_file (name, envvar, subdir);
452 }
453
454 ARDOUR::LocaleGuard::LocaleGuard (const char* str)
455 {
456         old = strdup (setlocale (LC_NUMERIC, NULL));
457         if (strcmp (old, str)) {
458                 setlocale (LC_NUMERIC, str);
459         } 
460 }
461
462 ARDOUR::LocaleGuard::~LocaleGuard ()
463 {
464         setlocale (LC_NUMERIC, old);
465         free ((char*)old);
466 }
467
468 ARDOUR::OverlapType
469 ARDOUR::coverage (jack_nframes_t sa, jack_nframes_t ea, 
470                   jack_nframes_t sb, jack_nframes_t eb)
471 {
472         /* OverlapType returned reflects how the second (B)
473            range overlaps the first (A).
474
475            The diagrams show various relative placements
476            of A and B for each OverlapType.
477
478            Notes:
479               Internal: the start points cannot coincide
480               External: the start and end points can coincide
481               Start: end points can coincide
482               End: start points can coincide
483
484            XXX Logically, Internal should disallow end
485            point equality.
486         */
487
488         /*
489              |--------------------|   A
490                   |------|            B
491                 |-----------------|   B
492
493
494              "B is internal to A"               
495
496         */
497 #ifdef OLD_COVERAGE
498         if ((sb >= sa) && (eb <= ea)) {
499 #else
500         if ((sb > sa) && (eb <= ea)) {
501 #endif
502                 return OverlapInternal;
503         }
504
505         /*
506              |--------------------|   A
507            ----|                      B
508            -----------------------|   B
509            --|                        B
510            
511              "B overlaps the start of A"
512
513         */
514
515         if ((eb >= sa) && (eb <= ea)) {
516                 return OverlapStart;
517         }
518         /* 
519              |---------------------|  A
520                    |----------------- B
521              |----------------------- B    
522                                    |- B
523
524             "B overlaps the end of A"                              
525
526         */
527         if ((sb >= sa) && (sb <= ea)) {
528                 return OverlapEnd;
529         }
530         /*
531              |--------------------|     A
532            --------------------------  B   
533              |-----------------------  B
534             ----------------------|    B
535              |--------------------|    B
536
537
538            "B overlaps all of A"
539         */
540         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
541                 return OverlapExternal;
542         }
543
544         return OverlapNone;
545 }
546
547 /* not sure where to put these */
548
549 std::istream& operator>>(std::istream& o, HeaderFormat hf) {
550         int val;
551         o >> val;
552         hf = (HeaderFormat) val;
553         return o;
554 }
555
556 std::istream& operator>>(std::istream& o, SampleFormat sf) {
557         int val;
558         o >> val;
559         sf = (SampleFormat) val;
560         return o;
561 }