2 Copyright (C) 2000 Paul Davis
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.
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.
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.
20 #include "libardour-config.h"
27 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
30 #include <sys/types.h>
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
40 #ifdef PLATFORM_WINDOWS
41 #include <windows.h> // for LARGE_INTEGER
44 #ifdef WINDOWS_VST_SUPPORT
49 #include "ardour/linux_vst_support.h"
52 #ifdef AUDIOUNIT_SUPPORT
53 #include "ardour/audio_unit.h"
56 #if defined(__SSE__) || defined(USE_XMMINTRIN)
57 #include <xmmintrin.h>
61 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
64 #include <glibmm/fileutils.h>
65 #include <glibmm/miscutils.h>
72 #include "pbd/error.h"
75 #include "pbd/strsplit.h"
77 #include "pbd/file_utils.h"
78 #include "pbd/enumwriter.h"
79 #include "pbd/basename.h"
81 #include "midi++/port.h"
82 #include "midi++/mmc.h"
84 #include "ardour/analyser.h"
85 #include "ardour/audio_library.h"
86 #include "ardour/audio_backend.h"
87 #include "ardour/audioengine.h"
88 #include "ardour/audioplaylist.h"
89 #include "ardour/audioregion.h"
90 #include "ardour/buffer_manager.h"
91 #include "ardour/control_protocol_manager.h"
92 #include "ardour/directory_names.h"
93 #include "ardour/event_type_map.h"
94 #include "ardour/filesystem_paths.h"
95 #include "ardour/midi_region.h"
96 #include "ardour/midiport_manager.h"
97 #include "ardour/mix.h"
98 #include "ardour/operations.h"
99 #include "ardour/panner_manager.h"
100 #include "ardour/plugin_manager.h"
101 #include "ardour/process_thread.h"
102 #include "ardour/profile.h"
103 #include "ardour/rc_configuration.h"
104 #include "ardour/region.h"
105 #include "ardour/route_group.h"
106 #include "ardour/runtime_functions.h"
107 #include "ardour/session_event.h"
108 #include "ardour/source_factory.h"
109 #include "ardour/uri_map.h"
111 #include "audiographer/routines.h"
113 #if defined (__APPLE__)
114 #include <Carbon/Carbon.h> // For Gestalt
119 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
120 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
121 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
123 using namespace ARDOUR;
127 bool libardour_initialized = false;
129 compute_peak_t ARDOUR::compute_peak = 0;
130 find_peaks_t ARDOUR::find_peaks = 0;
131 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
132 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
133 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
135 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
136 PBD::Signal3<void,std::string,std::string,bool> ARDOUR::PluginScanMessage;
137 PBD::Signal1<void,int> ARDOUR::PluginScanTimeout;
138 PBD::Signal0<void> ARDOUR::GUIIdle;
139 PBD::Signal3<bool,std::string,std::string,int> ARDOUR::CopyConfigurationFiles;
141 static bool have_old_configuration_files = false;
144 extern void setup_enum_writer ();
147 /* this is useful for quite a few things that want to check
148 if any bounds-related property has changed
150 PBD::PropertyChange ARDOUR::bounds_change;
153 setup_hardware_optimization (bool try_optimization)
155 bool generic_mix_functions = true;
157 if (try_optimization) {
161 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
165 info << "Using SSE optimized routines" << endmsg;
168 compute_peak = x86_sse_compute_peak;
169 find_peaks = x86_sse_find_peaks;
170 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
171 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
172 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
174 generic_mix_functions = false;
178 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
179 SInt32 sysVersion = 0;
181 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
184 if (sysVersion >= 0x00001040) { // Tiger at least
185 compute_peak = veclib_compute_peak;
186 find_peaks = veclib_find_peaks;
187 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
188 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
189 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
191 generic_mix_functions = false;
193 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
197 /* consider FPU denormal handling to be "h/w optimization" */
202 if (generic_mix_functions) {
204 compute_peak = default_compute_peak;
205 find_peaks = default_find_peaks;
206 apply_gain_to_buffer = default_apply_gain_to_buffer;
207 mix_buffers_with_gain = default_mix_buffers_with_gain;
208 mix_buffers_no_gain = default_mix_buffers_no_gain;
210 info << "No H/W specific optimizations in use" << endmsg;
213 AudioGrapher::Routines::override_compute_peak (compute_peak);
214 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
218 lotsa_files_please ()
220 #ifndef PLATFORM_WINDOWS
223 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
226 /* See the COMPATIBILITY note on the Apple setrlimit() man page */
227 rl.rlim_cur = min ((rlim_t) OPEN_MAX, rl.rlim_max);
229 rl.rlim_cur = rl.rlim_max;
232 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
233 if (rl.rlim_cur == RLIM_INFINITY) {
234 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
236 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
239 if (rl.rlim_cur != RLIM_INFINITY) {
240 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
244 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
250 copy_configuration_files (string const & old_dir, string const & new_dir, int old_version)
255 /* ensure target directory exists */
257 if (g_mkdir_with_parents (new_dir.c_str(), 0755)) {
261 if (old_version == 3) {
263 old_name = Glib::build_filename (old_dir, X_("recent"));
264 new_name = Glib::build_filename (new_dir, X_("recent"));
266 copy_file (old_name, new_name);
268 old_name = Glib::build_filename (old_dir, X_("sfdb"));
269 new_name = Glib::build_filename (new_dir, X_("sfdb"));
271 copy_file (old_name, new_name);
273 /* can only copy ardour.rc - UI config is not compatible */
275 old_name = Glib::build_filename (old_dir, X_("ardour.rc"));
276 new_name = Glib::build_filename (new_dir, X_("config"));
278 copy_file (old_name, new_name);
280 /* copy templates and route templates */
282 old_name = Glib::build_filename (old_dir, X_("templates"));
283 new_name = Glib::build_filename (new_dir, X_("templates"));
285 copy_recurse (old_name, new_name);
287 old_name = Glib::build_filename (old_dir, X_("route_templates"));
288 new_name = Glib::build_filename (new_dir, X_("route_templates"));
290 copy_recurse (old_name, new_name);
294 old_name = Glib::build_filename (old_dir, X_("presets"));
295 new_name = Glib::build_filename (new_dir, X_("presets"));
297 copy_recurse (old_name, new_name);
301 old_name = Glib::build_filename (old_dir, X_("plugin_statuses"));
302 new_name = Glib::build_filename (new_dir, X_("plugin_statuses"));
304 copy_file (old_name, new_name);
308 old_name = Glib::build_filename (old_dir, export_formats_dir_name);
309 new_name = Glib::build_filename (new_dir, export_formats_dir_name);
311 vector<string> export_formats;
312 g_mkdir_with_parents (Glib::build_filename (new_dir, export_formats_dir_name).c_str(), 0755);
313 find_files_matching_pattern (export_formats, old_name, X_("*.format"));
314 for (vector<string>::iterator i = export_formats.begin(); i != export_formats.end(); ++i) {
315 std::string from = *i;
316 std::string to = Glib::build_filename (new_name, Glib::path_get_basename (*i));
317 copy_file (from, to);
325 ARDOUR::check_for_old_configuration_files ()
327 int current_version = atoi (X_(PROGRAM_VERSION));
329 if (current_version <= 1) {
333 int old_version = current_version - 1;
335 string old_config_dir = user_config_directory (old_version);
336 /* pass in the current version explicitly to avoid creation */
337 string current_config_dir = user_config_directory (current_version);
339 if (!Glib::file_test (current_config_dir, Glib::FILE_TEST_IS_DIR)) {
340 if (Glib::file_test (old_config_dir, Glib::FILE_TEST_IS_DIR)) {
341 have_old_configuration_files = true;
347 ARDOUR::handle_old_configuration_files (boost::function<bool (std::string const&, std::string const&, int)> ui_handler)
349 if (have_old_configuration_files) {
350 int current_version = atoi (X_(PROGRAM_VERSION));
351 assert (current_version > 1); // established in check_for_old_configuration_files ()
352 int old_version = current_version - 1;
353 string old_config_dir = user_config_directory (old_version);
354 string current_config_dir = user_config_directory (current_version);
356 if (ui_handler (old_config_dir, current_config_dir, old_version)) {
357 copy_configuration_files (old_config_dir, current_config_dir, old_version);
365 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
367 if (libardour_initialized) {
371 if (!PBD::init()) return false;
374 (void) bindtextdomain(PACKAGE, localedir);
375 (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
378 SessionEvent::init_event_pool ();
380 Operations::make_operations_quarks ();
381 SessionObject::make_property_quarks ();
382 Region::make_property_quarks ();
383 MidiRegion::make_property_quarks ();
384 AudioRegion::make_property_quarks ();
385 RouteGroup::make_property_quarks ();
386 Playlist::make_property_quarks ();
387 AudioPlaylist::make_property_quarks ();
389 /* this is a useful ready to use PropertyChange that many
390 things need to check. This avoids having to compose
391 it every time we want to check for any of the relevant
395 bounds_change.add (ARDOUR::Properties::start);
396 bounds_change.add (ARDOUR::Properties::position);
397 bounds_change.add (ARDOUR::Properties::length);
399 /* provide a state version for the few cases that need it and are not
400 driven by reading state from disk (e.g. undo/redo)
403 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
405 ARDOUR::setup_enum_writer ();
407 // allow ardour the absolute maximum number of open files
408 lotsa_files_please ();
413 Library = new AudioLibrary;
415 BootMessage (_("Loading configuration"));
417 Config = new RCConfiguration;
419 if (Config->load_state ()) {
423 Config->set_use_windows_vst (use_windows_vst);
425 Config->set_use_lxvst(true);
428 Profile = new RuntimeProfile;
431 #ifdef WINDOWS_VST_SUPPORT
432 if (Config->get_use_windows_vst() && fst_init (0)) {
438 if (Config->get_use_lxvst() && vstfx_init (0)) {
443 #ifdef AUDIOUNIT_SUPPORT
444 AUPluginInfo::load_cached_info ();
447 setup_hardware_optimization (try_optimization);
449 SourceFactory::init ();
452 /* singletons - first object is "it" */
453 (void) PluginManager::instance();
455 (void) URIMap::instance();
457 (void) EventTypeMap::instance();
459 ProcessThread::init ();
460 /* the + 4 is a bit of a handwave. i don't actually know
461 how many more per-thread buffer sets we need above
462 the h/w concurrency, but its definitely > 1 more.
464 BufferManager::init (hardware_concurrency() + 4);
466 PannerManager::instance().discover_panners();
468 ARDOUR::AudioEngine::create ();
470 libardour_initialized = true;
476 ARDOUR::init_post_engine ()
478 ControlProtocolManager::instance().discover_control_protocols ();
481 if ((node = Config->control_protocol_state()) != 0) {
482 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
487 ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
493 if (!libardour_initialized) {
497 ARDOUR::AudioEngine::destroy ();
503 delete &ControlProtocolManager::instance();
504 #ifdef WINDOWS_VST_SUPPORT
511 delete &PluginManager::instance();
519 ARDOUR::find_bindings_files (map<string,string>& files)
521 vector<std::string> found;
522 Searchpath spath = ardour_config_search_path();
524 if (getenv ("ARDOUR_SAE")) {
525 find_files_matching_pattern (found, spath, "*SAE-*.bindings");
527 find_files_matching_pattern (found, spath, "*.bindings");
534 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
535 std::string path(*x);
536 pair<string,string> namepath;
537 namepath.second = path;
538 namepath.first = PBD::basename_nosuffix (path);
539 files.insert (namepath);
544 ARDOUR::no_auto_connect()
546 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
553 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
554 // valgrind doesn't understand this assembler stuff
555 // September 10th, 2007
559 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
564 /* XXX use real code to determine if the processor supports
565 DenormalsAreZero and FlushToZero
568 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
572 MXCSR = _mm_getcsr();
574 #ifdef DEBUG_DENORMAL_EXCEPTION
575 /* This will raise a FP exception if a denormal is detected */
576 MXCSR &= ~_MM_MASK_DENORM;
579 switch (Config->get_denormal_model()) {
581 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
585 if (fpu.has_flush_to_zero()) {
586 MXCSR |= _MM_FLUSH_ZERO_ON;
591 MXCSR &= ~_MM_FLUSH_ZERO_ON;
592 if (fpu.has_denormals_are_zero()) {
598 if (fpu.has_flush_to_zero()) {
599 if (fpu.has_denormals_are_zero()) {
600 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
602 MXCSR |= _MM_FLUSH_ZERO_ON;
613 /* this can be changed to modify the translation behaviour for
614 cases where the user has never expressed a preference.
616 static const bool translate_by_default = true;
619 ARDOUR::translation_enable_path ()
621 return Glib::build_filename (user_config_directory(), ".translate");
625 ARDOUR::translations_are_enabled ()
627 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
630 return translate_by_default;
636 if (::read (fd, &c, 1) == 1 && c == '1') {
646 ARDOUR::set_translations_enabled (bool yn)
648 string i18n_enabler = ARDOUR::translation_enable_path();
649 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
663 (void) ::write (fd, &c, 1);
671 ARDOUR::get_available_sync_options ()
673 vector<SyncSource> ret;
675 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
676 if (backend && backend->name() == "JACK") {
677 ret.push_back (Engine);
681 ret.push_back (MIDIClock);
687 /** Return a monotonic value for the number of microseconds that have elapsed
688 * since an arbitrary zero origin.
692 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
694 #include <mach/mach_time.h>
695 #define CLOCK_REALTIME 0
696 #define CLOCK_MONOTONIC 0
698 clock_gettime (int /*clk_id*/, struct timespec *t)
700 static bool initialized = false;
701 static mach_timebase_info_data_t timebase;
703 mach_timebase_info(&timebase);
707 time = mach_absolute_time();
708 double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
709 double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
711 t->tv_nsec = nseconds;
717 ARDOUR::get_microseconds ()
719 #ifdef PLATFORM_WINDOWS
720 microseconds_t ret = 0;
721 LARGE_INTEGER freq, time;
723 if (QueryPerformanceFrequency(&freq))
724 if (QueryPerformanceCounter(&time))
725 ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
730 if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
734 return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
738 /** Return the number of bits per sample for a given sample format.
740 * This is closely related to sndfile_data_width() but does NOT
741 * return a "magic" value to differentiate between 32 bit integer
742 * and 32 bit floating point values.
746 ARDOUR::format_data_width (ARDOUR::SampleFormat format)
752 case ARDOUR::FormatInt16:
754 case ARDOUR::FormatInt24: