add latency callback to dummy backend
[ardour.git] / libs / backends / dummy / dummy_audiobackend.cc
index be157f12f0b0f070bf79431fc2c0b308fcb70735..cd09a64c6590f22c71f57bb35807fe5cedad4e79 100644 (file)
@@ -47,6 +47,7 @@ DummyAudioBackend::DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info)
        , _systemic_input_latency (0)
        , _systemic_output_latency (0)
        , _processed_samples (0)
+       , _port_change_flag (false)
 {
        _instance_name = s_instance_name;
        pthread_mutex_init (&_port_callback_mutex, 0);
@@ -311,14 +312,17 @@ DummyAudioBackend::_start (bool /*for_latency_measurement*/)
                return -1;
        }
 
+       engine.sample_rate_change (_samplerate);
+       engine.buffer_size_change (_samples_per_period);
+
        if (engine.reestablish_ports ()) {
                PBD::error << _("DummyAudioBackend: Could not re-establish ports.") << endmsg;
                stop ();
                return -1;
        }
 
-       engine.buffer_size_change (_samples_per_period);
        engine.reconnect_ports ();
+       _port_change_flag = false;
 
        if (pthread_create (&_main_thread, NULL, pthread_process, this)) {
                PBD::error << _("DummyAudioBackend: cannot start.") << endmsg;
@@ -471,6 +475,8 @@ DummyAudioBackend::process_thread_count ()
 void
 DummyAudioBackend::update_latencies ()
 {
+       // trigger latency callback in RT thread (locked graph)
+       port_connect_add_remove_callback();
 }
 
 /* PORTENGINE API */
@@ -648,7 +654,7 @@ DummyAudioBackend::register_system_ports()
                snprintf(tmp, sizeof(tmp), "system:playback_%d", i);
                PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
                if (!p) return -1;
-               set_latency_range (p, false, lr);
+               set_latency_range (p, true, lr);
        }
 
        /* midi ports */
@@ -667,9 +673,8 @@ DummyAudioBackend::register_system_ports()
                snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", i);
                PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
                if (!p) return -1;
-               set_latency_range (p, false, lr);
+               set_latency_range (p, true, lr);
        }
-
        return 0;
 }
 
@@ -1004,6 +1009,9 @@ DummyAudioBackend::main_process_thread ()
        _running = true;
        _processed_samples = 0;
 
+       manager.registration_callback();
+       manager.graph_order_callback();
+
        uint64_t clock1, clock2;
        clock1 = g_get_monotonic_time();
        while (_running) {
@@ -1027,7 +1035,16 @@ DummyAudioBackend::main_process_thread ()
                }
                clock1 = g_get_monotonic_time();
 
+               bool connections_changed = false;
+               bool ports_changed = false;
                if (!pthread_mutex_trylock (&_port_callback_mutex)) {
+                       if (_port_change_flag) {
+                               ports_changed = true;
+                               _port_change_flag = false;
+                       }
+                       if (!_port_connection_queue.empty ()) {
+                               connections_changed = true;
+                       }
                        while (!_port_connection_queue.empty ()) {
                                PortConnectData *c = _port_connection_queue.back ();
                                manager.connect_callback (c->a, c->b, c->c);
@@ -1036,6 +1053,16 @@ DummyAudioBackend::main_process_thread ()
                        }
                        pthread_mutex_unlock (&_port_callback_mutex);
                }
+               if (ports_changed) {
+                       manager.registration_callback();
+               }
+               if (connections_changed) {
+                       manager.graph_order_callback();
+               }
+               if (connections_changed || ports_changed) {
+                       engine.latency_callback(false);
+                       engine.latency_callback(true);
+               }
 
        }
        _running = false;
@@ -1105,10 +1132,12 @@ DummyPort::DummyPort (DummyAudioBackend &b, const std::string& name, PortFlags f
        _capture_latency_range.max = 0;
        _playback_latency_range.min = 0;
        _playback_latency_range.max = 0;
+       _dummy_backend.port_connect_add_remove_callback();
 }
 
 DummyPort::~DummyPort () {
        disconnect_all ();
+       _dummy_backend.port_connect_add_remove_callback();
 }
 
 
@@ -1264,6 +1293,12 @@ DummyMidiPort::DummyMidiPort (DummyAudioBackend &b, const std::string& name, Por
 
 DummyMidiPort::~DummyMidiPort () { }
 
+struct MidiEventSorter {
+       bool operator() (const boost::shared_ptr<DummyMidiEvent>& a, const boost::shared_ptr<DummyMidiEvent>& b) {
+               return *a < *b;
+       }
+};
+
 void* DummyMidiPort::get_buffer (pframes_t /* nframes */)
 {
        if (is_input ()) {
@@ -1276,7 +1311,7 @@ void* DummyMidiPort::get_buffer (pframes_t /* nframes */)
                                _buffer.push_back (boost::shared_ptr<DummyMidiEvent>(new DummyMidiEvent (**it)));
                        }
                }
-               std::sort (_buffer.begin (), _buffer.end ());
+               std::sort (_buffer.begin (), _buffer.end (), MidiEventSorter());
        } else if (is_output () && is_physical () && is_terminal()) {
                _buffer.clear ();
        }