fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / audioengine.cc
index 3d0cfca523c56958e48aa0264bb2dd298b4fac95..30c2113c06ad39fe7e23d3f695e985c3586e7db1 100644 (file)
@@ -55,7 +55,7 @@
 #include "ardour/process_thread.h"
 #include "ardour/session.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -63,6 +63,8 @@ using namespace PBD;
 
 AudioEngine* AudioEngine::_instance = 0;
 
+static gint audioengine_thread_cnt = 1;
+
 #ifdef SILENCE_AFTER
 #define SILENCE_AFTER_SECONDS 600
 #endif
@@ -87,6 +89,7 @@ AudioEngine::AudioEngine ()
        , _stopped_for_latency (false)
        , _started_for_latency (false)
        , _in_destructor (false)
+       , _last_backend_error_string(AudioBackend::get_error_string((AudioBackend::ErrorCode)-1))
     , _hw_reset_event_thread(0)
     , _hw_reset_request_count(0)
     , _stop_hw_reset_processing(0)
@@ -111,6 +114,7 @@ AudioEngine::~AudioEngine ()
        for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
                i->second->deinstantiate();
        }
+       delete _main_thread;
 }
 
 AudioEngine*
@@ -214,6 +218,26 @@ AudioEngine::process_callback (pframes_t nframes)
                return 0;
        }
 
+       /* The coreaudio-backend calls thread_init_callback() if
+        * the hardware changes or pthread_self() changes.
+        *
+        * However there are cases when neither holds true, yet
+        * the thread-pool changes: e.g. connect a headphone to
+        * a shared mic/headphone jack.
+        * It's probably related to, or caused by clocksource changes.
+        *
+        * For reasons yet unknown Glib::Threads::Private() can
+        * use a different thread-private in the same pthread
+        * (coreaudio render callback).
+        *
+        * Coreaudio must set something which influences
+        * pthread_key_t uniqness or reset the key using
+        * pthread_getspecific().
+        */
+       if (! SessionEvent::has_per_thread_pool ()) {
+               thread_init_callback (NULL);
+       }
+
        bool return_after_remove_check = false;
 
        if (_measuring_latency == MeasureAudio && _mtdm) {
@@ -388,7 +412,7 @@ AudioEngine::process_callback (pframes_t nframes)
 
 #else
        if (_session->silent()) {
-               PortManager::silence (nframes);
+               PortManager::silence (nframes, _session);
        }
 #endif
 
@@ -866,6 +890,8 @@ AudioEngine::start (bool for_latency)
 int
 AudioEngine::stop (bool for_latency)
 {
+       bool stop_engine = true;
+
        if (!_backend) {
                return 0;
        }
@@ -876,15 +902,20 @@ AudioEngine::stop (bool for_latency)
                pl.acquire ();
        }
 
-       if (_backend->stop ()) {
-               return -1;
+       if (for_latency && _backend->can_change_systemic_latency_when_running()) {
+               stop_engine = false;
+       } else {
+               if (_backend->stop ()) {
+                       pl.release ();
+                       return -1;
+               }
        }
 
        if (pl.locked ()) {
                pl.release ();
        }
 
-       if (_session && _running &&
+       if (_session && _running && stop_engine &&
            (_session->state_of_the_state() & Session::Loading) == 0 &&
            (_session->state_of_the_state() & Session::Deletion) == 0) {
                // it's not a halt, but should be handled the same way:
@@ -892,16 +923,20 @@ AudioEngine::stop (bool for_latency)
                _session->engine_halted ();
        }
 
-       _running = false;
+       if (stop_engine) {
+               _running = false;
+       }
        _processed_frames = 0;
        _measuring_latency = MeasureNone;
        _latency_output_port = 0;
        _latency_input_port = 0;
        _started_for_latency = false;
 
-       Port::PortDrop ();
+       if (stop_engine) {
+               Port::PortDrop ();
+       }
 
-       if (!for_latency) {
+       if (!for_latency && stop_engine) {
                Stopped (); /* EMIT SIGNAL */
        }
 
@@ -1192,14 +1227,15 @@ AudioEngine::thread_init_callback (void* arg)
 
        pthread_set_name (X_("audioengine"));
 
-       SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
-
-       PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
-       PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
+       const int thread_num = g_atomic_int_add (&audioengine_thread_cnt, 1);
+       const string thread_name = string_compose (X_("AudioEngine %1"), thread_num);
 
+       SessionEvent::create_per_thread_pool (thread_name, 512);
+       PBD::notify_event_loops_about_thread_creation (pthread_self(), thread_name, 4096);
        AsyncMIDIPort::set_process_thread (pthread_self());
 
        if (arg) {
+               delete AudioEngine::instance()->_main_thread;
                /* the special thread created/managed by the backend */
                AudioEngine::instance()->_main_thread = new ProcessThread;
        }
@@ -1271,15 +1307,28 @@ AudioEngine::setup_required () const
 int
 AudioEngine::prepare_for_latency_measurement ()
 {
+       if (!_backend) {
+               return -1;
+       }
+
+       if (_backend->can_change_systemic_latency_when_running()) {
+               if (start()) {
+                       return -1;
+               }
+               _backend->set_systemic_input_latency (0);
+               _backend->set_systemic_output_latency (0);
+               return 0;
+       }
+
        if (running()) {
                _stopped_for_latency = true;
                stop (true);
        }
 
        if (start (true)) {
-               _started_for_latency = true;
                return -1;
        }
+       _started_for_latency = true;
 
        return 0;
 }
@@ -1287,10 +1336,8 @@ AudioEngine::prepare_for_latency_measurement ()
 int
 AudioEngine::start_latency_detection (bool for_midi)
 {
-       if (!running()) {
-               if (prepare_for_latency_measurement ()) {
-                       return -1;
-               }
+       if (prepare_for_latency_measurement ()) {
+               return -1;
        }
 
        PortEngine& pe (port_engine());
@@ -1397,7 +1444,9 @@ AudioEngine::stop_latency_detection ()
                _latency_input_port = 0;
        }
 
-       stop (true);
+       if (!_backend->can_change_systemic_latency_when_running()) {
+               stop (true);
+       }
 
        if (_stopped_for_latency) {
                start ();