auditioner always runs at normal speed, independent of transport speed
[ardour.git] / libs / ardour / globals.cc
index 09043430a366f12600fc6b10277579c59c476ef1..00d448985f555fadb6cb1ee25930f9bc7a738b4c 100644 (file)
 #include <time.h>
 
 #include <glib.h>
 #include <time.h>
 
 #include <glib.h>
-#include <pbd/gstdio_compat.h>
+#include "pbd/gstdio_compat.h"
 
 #ifdef PLATFORM_WINDOWS
 
 #ifdef PLATFORM_WINDOWS
+#include <stdio.h> // for _setmaxstdio
 #include <windows.h> // for LARGE_INTEGER
 #endif
 
 #include <windows.h> // for LARGE_INTEGER
 #endif
 
@@ -62,7 +63,7 @@
 
 #ifdef check
 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
 
 #ifdef check
 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
-#endif 
+#endif
 
 #include <glibmm/fileutils.h>
 #include <glibmm/miscutils.h>
 
 #include <glibmm/fileutils.h>
 #include <glibmm/miscutils.h>
 #include "pbd/fpu.h"
 #include "pbd/file_utils.h"
 #include "pbd/enumwriter.h"
 #include "pbd/fpu.h"
 #include "pbd/file_utils.h"
 #include "pbd/enumwriter.h"
-#include "pbd/basename.h"
 
 #include "midi++/port.h"
 #include "midi++/mmc.h"
 
 
 #include "midi++/port.h"
 #include "midi++/mmc.h"
 
+#include "LuaBridge/LuaBridge.h"
+
 #include "ardour/analyser.h"
 #include "ardour/audio_library.h"
 #include "ardour/audio_backend.h"
 #include "ardour/analyser.h"
 #include "ardour/audio_library.h"
 #include "ardour/audio_backend.h"
 #include "ardour/event_type_map.h"
 #include "ardour/filesystem_paths.h"
 #include "ardour/midi_region.h"
 #include "ardour/event_type_map.h"
 #include "ardour/filesystem_paths.h"
 #include "ardour/midi_region.h"
+#include "ardour/midi_ui.h"
 #include "ardour/midiport_manager.h"
 #include "ardour/mix.h"
 #include "ardour/operations.h"
 #include "ardour/panner_manager.h"
 #include "ardour/plugin_manager.h"
 #include "ardour/midiport_manager.h"
 #include "ardour/mix.h"
 #include "ardour/operations.h"
 #include "ardour/panner_manager.h"
 #include "ardour/plugin_manager.h"
+#include "ardour/presentation_info.h"
 #include "ardour/process_thread.h"
 #include "ardour/profile.h"
 #include "ardour/rc_configuration.h"
 #include "ardour/process_thread.h"
 #include "ardour/profile.h"
 #include "ardour/rc_configuration.h"
 #include "ardour/runtime_functions.h"
 #include "ardour/session_event.h"
 #include "ardour/source_factory.h"
 #include "ardour/runtime_functions.h"
 #include "ardour/session_event.h"
 #include "ardour/source_factory.h"
+#ifdef LV2_SUPPORT
 #include "ardour/uri_map.h"
 #include "ardour/uri_map.h"
-
+#endif
 #include "audiographer/routines.h"
 
 #if defined (__APPLE__)
 #include "audiographer/routines.h"
 
 #if defined (__APPLE__)
-       #include <Carbon/Carbon.h> // For Gestalt
+#include <CoreFoundation/CoreFoundation.h>
 #endif
 
 #endif
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
 
 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
@@ -142,7 +147,7 @@ PBD::Signal1<void,int> ARDOUR::PluginScanTimeout;
 PBD::Signal0<void> ARDOUR::GUIIdle;
 PBD::Signal3<bool,std::string,std::string,int> ARDOUR::CopyConfigurationFiles;
 
 PBD::Signal0<void> ARDOUR::GUIIdle;
 PBD::Signal3<bool,std::string,std::string,int> ARDOUR::CopyConfigurationFiles;
 
-std::vector<std::string> ARDOUR::reserved_io_names;
+std::map<std::string, bool> ARDOUR::reserved_io_names;
 
 static bool have_old_configuration_files = false;
 
 
 static bool have_old_configuration_files = false;
 
@@ -168,15 +173,15 @@ setup_hardware_optimization (bool try_optimization)
 
 #ifdef PLATFORM_WINDOWS
                /* We have AVX-optimized code for Windows */
 
 #ifdef PLATFORM_WINDOWS
                /* We have AVX-optimized code for Windows */
-               
+
                if (fpu->has_avx()) {
                if (fpu->has_avx()) {
-#else                  
+#else
                /* AVX code doesn't compile on Linux yet */
                /* AVX code doesn't compile on Linux yet */
-               
+
                if (false) {
                if (false) {
-#endif                 
+#endif
                        info << "Using AVX optimized routines" << endmsg;
                        info << "Using AVX optimized routines" << endmsg;
-                       
+
                        // AVX SET
                        compute_peak          = x86_sse_avx_compute_peak;
                        find_peaks            = x86_sse_avx_find_peaks;
                        // AVX SET
                        compute_peak          = x86_sse_avx_compute_peak;
                        find_peaks            = x86_sse_avx_find_peaks;
@@ -204,12 +209,8 @@ setup_hardware_optimization (bool try_optimization)
                }
 
 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
                }
 
 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
-               SInt32 sysVersion = 0;
 
 
-               if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
-                       sysVersion = 0;
-
-               if (sysVersion >= 0x00001040) { // Tiger at least
+               if (floor (kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_4) { /* at least Tiger */
                        compute_peak           = veclib_compute_peak;
                        find_peaks             = veclib_find_peaks;
                        apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
                        compute_peak           = veclib_compute_peak;
                        find_peaks             = veclib_find_peaks;
                        apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
@@ -273,6 +274,21 @@ lotsa_files_please ()
        } else {
                error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
        }
        } else {
                error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
        }
+#else
+       /* this only affects stdio. 2048 is the maxium possible (512 the default).
+        *
+        * If we want more, we'll have to replaces the POSIX I/O interfaces with
+        * Win32 API calls (CreateFile, WriteFile, etc) which allows for 16K.
+        *
+        * see http://stackoverflow.com/questions/870173/is-there-a-limit-on-number-of-open-files-in-windows
+        * and http://bugs.mysql.com/bug.php?id=24509
+        */
+       int newmax = _setmaxstdio (2048);
+       if (newmax > 0) {
+               info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, newmax) << endmsg;
+       } else {
+               error << string_compose (_("Could not set system open files limit. Current limit is %1 open files"), _getmaxstdio())  << endmsg;
+       }
 #endif
 }
 
 #endif
 }
 
@@ -287,9 +303,9 @@ copy_configuration_files (string const & old_dir, string const & new_dir, int ol
        if (g_mkdir_with_parents (new_dir.c_str(), 0755)) {
                return -1;
        }
        if (g_mkdir_with_parents (new_dir.c_str(), 0755)) {
                return -1;
        }
-       
-       if (old_version == 3) {
-       
+
+       if (old_version >= 3) {
+
                old_name = Glib::build_filename (old_dir, X_("recent"));
                new_name = Glib::build_filename (new_dir, X_("recent"));
 
                old_name = Glib::build_filename (old_dir, X_("recent"));
                new_name = Glib::build_filename (new_dir, X_("recent"));
 
@@ -307,7 +323,7 @@ copy_configuration_files (string const & old_dir, string const & new_dir, int ol
                 * $CONFIG/ardour.rc. Pick up the newer "old" config file,
                 * to avoid confusion.
                 */
                 * $CONFIG/ardour.rc. Pick up the newer "old" config file,
                 * to avoid confusion.
                 */
-               
+
                string old_name = Glib::build_filename (old_dir, X_("config"));
 
                if (!Glib::file_test (old_name, Glib::FILE_TEST_EXISTS)) {
                string old_name = Glib::build_filename (old_dir, X_("config"));
 
                if (!Glib::file_test (old_name, Glib::FILE_TEST_EXISTS)) {
@@ -334,7 +350,7 @@ copy_configuration_files (string const & old_dir, string const & new_dir, int ol
 
                old_name = Glib::build_filename (old_dir, X_("presets"));
                new_name = Glib::build_filename (new_dir, X_("presets"));
 
                old_name = Glib::build_filename (old_dir, X_("presets"));
                new_name = Glib::build_filename (new_dir, X_("presets"));
-               
+
                copy_recurse (old_name, new_name);
 
                /* presets */
                copy_recurse (old_name, new_name);
 
                /* presets */
@@ -343,12 +359,12 @@ copy_configuration_files (string const & old_dir, string const & new_dir, int ol
                new_name = Glib::build_filename (new_dir, X_("plugin_statuses"));
 
                copy_file (old_name, new_name);
                new_name = Glib::build_filename (new_dir, X_("plugin_statuses"));
 
                copy_file (old_name, new_name);
-               
+
                /* export formats */
 
                old_name = Glib::build_filename (old_dir, export_formats_dir_name);
                new_name = Glib::build_filename (new_dir, export_formats_dir_name);
                /* export formats */
 
                old_name = Glib::build_filename (old_dir, export_formats_dir_name);
                new_name = Glib::build_filename (new_dir, export_formats_dir_name);
-               
+
                vector<string> export_formats;
                g_mkdir_with_parents (Glib::build_filename (new_dir, export_formats_dir_name).c_str(), 0755);
                find_files_matching_pattern (export_formats, old_name, X_("*.format"));
                vector<string> export_formats;
                g_mkdir_with_parents (Glib::build_filename (new_dir, export_formats_dir_name).c_str(), 0755);
                find_files_matching_pattern (export_formats, old_name, X_("*.format"));
@@ -366,7 +382,7 @@ void
 ARDOUR::check_for_old_configuration_files ()
 {
        int current_version = atoi (X_(PROGRAM_VERSION));
 ARDOUR::check_for_old_configuration_files ()
 {
        int current_version = atoi (X_(PROGRAM_VERSION));
-       
+
        if (current_version <= 1) {
                return;
        }
        if (current_version <= 1) {
                return;
        }
@@ -409,6 +425,12 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
                return true;
        }
 
                return true;
        }
 
+#ifndef NDEBUG
+       if (getenv("LUA_METATABLES")) {
+               luabridge::Security::setHideMetatables (false);
+       }
+#endif
+
        if (!PBD::init()) return false;
 
 #ifdef ENABLE_NLS
        if (!PBD::init()) return false;
 
 #ifdef ENABLE_NLS
@@ -426,6 +448,7 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
        RouteGroup::make_property_quarks ();
         Playlist::make_property_quarks ();
         AudioPlaylist::make_property_quarks ();
        RouteGroup::make_property_quarks ();
         Playlist::make_property_quarks ();
         AudioPlaylist::make_property_quarks ();
+        PresentationInfo::make_property_quarks ();
 
        /* this is a useful ready to use PropertyChange that many
           things need to check. This avoids having to compose
 
        /* this is a useful ready to use PropertyChange that many
           things need to check. This avoids having to compose
@@ -497,12 +520,28 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
 #endif
        (void) EventTypeMap::instance();
 
 #endif
        (void) EventTypeMap::instance();
 
+       ControlProtocolManager::instance().discover_control_protocols ();
+
+       /* for each control protocol, check for a request buffer factory method
+          and if it exists, store it in the EventLoop list of such
+          methods. This allows the relevant threads to register themselves
+          with EventLoops so that signal emission can be RT-safe.
+       */
+
+       ControlProtocolManager::instance().register_request_buffer_factories ();
+       /* it would be nice if this could auto-register itself in the
+          constructor, since MidiControlUI is a singleton, but it can't be
+          created until after the engine is running. Therefore we have to
+          explicitly register it here.
+       */
+       EventLoop::register_request_buffer_factory (X_("midiUI"), MidiControlUI::request_factory);
+
         ProcessThread::init ();
        /* the + 4 is a bit of a handwave. i don't actually know
           how many more per-thread buffer sets we need above
           the h/w concurrency, but its definitely > 1 more.
        */
         ProcessThread::init ();
        /* the + 4 is a bit of a handwave. i don't actually know
           how many more per-thread buffer sets we need above
           the h/w concurrency, but its definitely > 1 more.
        */
-        BufferManager::init (hardware_concurrency() + 4); 
+        BufferManager::init (hardware_concurrency() + 4);
 
         PannerManager::instance().discover_panners();
 
 
         PannerManager::instance().discover_panners();
 
@@ -511,24 +550,28 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
        /* it is unfortunate that we need to include reserved names here that
           refer to control surfaces. But there's no way to ensure a complete
           lack of collisions without doing this, since the control surface
        /* it is unfortunate that we need to include reserved names here that
           refer to control surfaces. But there's no way to ensure a complete
           lack of collisions without doing this, since the control surface
-          support may not even be active. Without adding an API to control 
+          support may not even be active. Without adding an API to control
           surface support that would list their port names, we do have to
           list them here.
           surface support that would list their port names, we do have to
           list them here.
+
+          We also need to know if the given I/O is an actual route.
+          For routes (e.g. "master"), bus creation needs to be allowed the first time,
+          while for pure I/O (e.g. "Click") track/bus creation must always fail.
        */
        */
-       
-       char const * const reserved[] = {
-               _("Monitor"),
-               _("Master"),
-               _("Control"),
-               _("Click"),
-               _("Mackie"),
-               0
-       };
-
-       for (int n = 0; reserved[n]; ++n) {
-               reserved_io_names.push_back (reserved[n]);
-       }
-       
+
+       reserved_io_names[_("Monitor")] = true;
+       reserved_io_names[_("Master")] = true;
+       reserved_io_names["auditioner"] = true; // auditioner.cc  Track (s, "auditioner",...)
+
+       /* pure I/O */
+       reserved_io_names[X_("Click")] = false; // session.cc ClickIO (*this, X_("Click")
+       reserved_io_names[_("Control")] = false;
+       reserved_io_names[_("Mackie")] = false;
+       reserved_io_names[_("FaderPort Recv")] = false;
+       reserved_io_names[_("FaderPort Send")] = false;
+       reserved_io_names[_("FaderPort8 Recv")] = false;
+       reserved_io_names[_("FaderPort8 Send")] = false;
+
        libardour_initialized = true;
 
        return true;
        libardour_initialized = true;
 
        return true;
@@ -537,8 +580,6 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
 void
 ARDOUR::init_post_engine ()
 {
 void
 ARDOUR::init_post_engine ()
 {
-       ControlProtocolManager::instance().discover_control_protocols ();
-
        XMLNode* node;
        if ((node = Config->control_protocol_state()) != 0) {
                ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
        XMLNode* node;
        if ((node = Config->control_protocol_state()) != 0) {
                ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
@@ -550,19 +591,19 @@ ARDOUR::init_post_engine ()
 }
 
 void
 }
 
 void
-ARDOUR::cleanup () 
+ARDOUR::cleanup ()
 {
        if (!libardour_initialized) {
                return;
        }
 
 {
        if (!libardour_initialized) {
                return;
        }
 
+       delete &ControlProtocolManager::instance();
        ARDOUR::AudioEngine::destroy ();
 
        delete Library;
 #ifdef HAVE_LRDF
        lrdf_cleanup ();
 #endif
        ARDOUR::AudioEngine::destroy ();
 
        delete Library;
 #ifdef HAVE_LRDF
        lrdf_cleanup ();
 #endif
-       delete &ControlProtocolManager::instance();
 #ifdef WINDOWS_VST_SUPPORT
        fst_exit ();
 #endif
 #ifdef WINDOWS_VST_SUPPORT
        fst_exit ();
 #endif
@@ -577,31 +618,6 @@ ARDOUR::cleanup ()
        return;
 }
 
        return;
 }
 
-void
-ARDOUR::find_bindings_files (map<string,string>& files)
-{
-       vector<std::string> found;
-       Searchpath spath = ardour_config_search_path();
-
-       if (getenv ("ARDOUR_SAE")) {
-               find_files_matching_pattern (found, spath, "*SAE-*.bindings");
-       } else {
-               find_files_matching_pattern (found, spath, "*.bindings");
-       }
-
-       if (found.empty()) {
-               return;
-       }
-
-       for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
-               std::string path(*x);
-               pair<string,string> namepath;
-               namepath.second = path;
-               namepath.first = PBD::basename_nosuffix (path);
-               files.insert (namepath);
-       }
-}
-
 bool
 ARDOUR::no_auto_connect()
 {
 bool
 ARDOUR::no_auto_connect()
 {
@@ -612,7 +628,7 @@ void
 ARDOUR::setup_fpu ()
 {
        FPU* fpu = FPU::instance ();
 ARDOUR::setup_fpu ()
 {
        FPU* fpu = FPU::instance ();
-       
+
        if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
                // valgrind doesn't understand this assembler stuff
                // September 10th, 2007
        if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
                // valgrind doesn't understand this assembler stuff
                // September 10th, 2007
@@ -632,7 +648,7 @@ ARDOUR::setup_fpu ()
 #ifdef DEBUG_DENORMAL_EXCEPTION
        /* This will raise a FP exception if a denormal is detected */
        MXCSR &= ~_MM_MASK_DENORM;
 #ifdef DEBUG_DENORMAL_EXCEPTION
        /* This will raise a FP exception if a denormal is detected */
        MXCSR &= ~_MM_MASK_DENORM;
-#endif 
+#endif
 
        switch (Config->get_denormal_model()) {
        case DenormalNone:
 
        switch (Config->get_denormal_model()) {
        case DenormalNone:
@@ -709,18 +725,19 @@ ARDOUR::set_translations_enabled (bool yn)
        if (fd < 0) {
                return false;
        }
        if (fd < 0) {
                return false;
        }
-       
+
        char c;
        char c;
-       
+
        if (yn) {
                c = '1';
        } else {
                c = '0';
        }
        if (yn) {
                c = '1';
        } else {
                c = '0';
        }
-       
+
        (void) ::write (fd, &c, 1);
        (void) ::close (fd);
 
        (void) ::write (fd, &c, 1);
        (void) ::close (fd);
 
+       Config->ParameterChanged ("enable-translation");
        return true;
 }
 
        return true;
 }
 
@@ -752,7 +769,7 @@ ARDOUR::get_available_sync_options ()
 #include <mach/mach_time.h>
 #define CLOCK_REALTIME 0
 #define CLOCK_MONOTONIC 0
 #include <mach/mach_time.h>
 #define CLOCK_REALTIME 0
 #define CLOCK_MONOTONIC 0
-int 
+int
 clock_gettime (int /*clk_id*/, struct timespec *t)
 {
         static bool initialized = false;
 clock_gettime (int /*clk_id*/, struct timespec *t)
 {
         static bool initialized = false;
@@ -770,7 +787,7 @@ clock_gettime (int /*clk_id*/, struct timespec *t)
         return 0;
 }
 #endif
         return 0;
 }
 #endif
+
 microseconds_t
 ARDOUR::get_microseconds ()
 {
 microseconds_t
 ARDOUR::get_microseconds ()
 {