From 1ab61b8564f9934c533d1c1a229888bc7e2fd557 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 7 Aug 2013 22:22:11 -0400 Subject: major redesign of MIDI port heirarchy and management (part 2) --- libs/ardour/ladspa_plugin.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'libs/ardour/ladspa_plugin.cc') diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index 5a6e577f2d..6a2636e4f4 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -36,8 +36,6 @@ #include "pbd/xml++.h" #include "pbd/stacktrace.h" -#include "midi++/manager.h" - #include "ardour/session.h" #include "ardour/ladspa_plugin.h" #include "ardour/buffer_set.h" -- cgit v1.2.3 From d90e2b42211ead2a38afd5590e2937992312795e Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 8 Aug 2013 16:31:08 -0400 Subject: rationalize (a bit) engine start/stop/restart so that it is possible to start up, disconnect from JACK and then reconnect --- gtk2_ardour/ardour_ui.cc | 226 +++++++++++++++++---------------- gtk2_ardour/ardour_ui.h | 1 + gtk2_ardour/arval | 1 + libs/ardour/ardour/jack_audiobackend.h | 12 +- libs/ardour/ardour/jack_portengine.h | 1 + libs/ardour/ardour/port_engine.h | 2 + libs/ardour/audioengine.cc | 80 ++++++------ libs/ardour/jack_audiobackend.cc | 41 +++--- libs/ardour/jack_portengine.cc | 6 + libs/ardour/ladspa_plugin.cc | 2 + libs/ardour/midi_buffer.cc | 6 +- libs/ardour/midi_port.cc | 1 + libs/ardour/port.cc | 14 +- libs/ardour/port_manager.cc | 4 +- 14 files changed, 214 insertions(+), 183 deletions(-) (limited to 'libs/ardour/ladspa_plugin.cc') diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index ba53468414..00767b7988 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -161,6 +161,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , nsm (0) , _was_dirty (false) , _mixer_on_top (false) + , first_time_engine_run (true) /* transport */ @@ -414,10 +415,122 @@ ARDOUR_UI::attach_to_engine () } } +void +ARDOUR_UI::engine_stopped () +{ + ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped) + ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false); + ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); +} + +void +ARDOUR_UI::engine_running () +{ + if (first_time_engine_run) { + post_engine(); + first_time_engine_run = false; + } + + ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true); + ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false); + + Glib::RefPtr action; + const char* action_name = 0; + + switch (engine->samples_per_cycle()) { + case 32: + action_name = X_("JACKLatency32"); + break; + case 64: + action_name = X_("JACKLatency64"); + break; + case 128: + action_name = X_("JACKLatency128"); + break; + case 512: + action_name = X_("JACKLatency512"); + break; + case 1024: + action_name = X_("JACKLatency1024"); + break; + case 2048: + action_name = X_("JACKLatency2048"); + break; + case 4096: + action_name = X_("JACKLatency4096"); + break; + case 8192: + action_name = X_("JACKLatency8192"); + break; + default: + /* XXX can we do anything useful ? */ + break; + } + + if (action_name) { + + action = ActionManager::get_action (X_("JACK"), action_name); + + if (action) { + Glib::RefPtr ract = Glib::RefPtr::cast_dynamic (action); + ract->set_active (); + } + + update_disk_space (); + update_cpu_load (); + update_sample_rate (engine->sample_rate()); + update_timecode_format (); + } +} + +void +ARDOUR_UI::engine_halted (const char* reason, bool free_reason) +{ + if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { + /* we can't rely on the original string continuing to exist when we are called + again in the GUI thread, so make a copy and note that we need to + free it later. + */ + char *copy = strdup (reason); + Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true)); + return; + } + + ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false); + ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); + + update_sample_rate (0); + + string msgstr; + + /* if the reason is a non-empty string, it means that the backend was shutdown + rather than just Ardour. + */ + + if (strlen (reason)) { + msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason); + } else { + msgstr = string_compose (_("\ +JACK has either been shutdown or it\n\ +disconnected %1 because %1\n\ +was not fast enough. Try to restart\n\ +JACK, reconnect and save the session."), PROGRAM_NAME); + } + + MessageDialog msg (*editor, msgstr); + pop_back_splash (msg); + msg.set_keep_above (true); + msg.run (); + + if (free_reason) { + free (const_cast (reason)); + } +} + void ARDOUR_UI::post_engine () { - /* Things to be done once we have a backend running in the AudioEngine + /* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine */ ARDOUR::init_post_engine (); @@ -483,11 +596,6 @@ ARDOUR_UI::post_engine () Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1); #endif - update_disk_space (); - update_cpu_load (); - update_sample_rate (engine->sample_rate()); - update_timecode_format (); - Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context()); boost::function pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1)); Config->map_parameters (pc); @@ -1042,7 +1150,7 @@ ARDOUR_UI::update_sample_rate (framecnt_t) if (!engine->connected()) { - snprintf (buf, sizeof (buf), "%s", _("disconnected")); + snprintf (buf, sizeof (buf), _("Audio: none")); } else { @@ -2041,110 +2149,6 @@ ARDOUR_UI::map_transport_state () } } -void -ARDOUR_UI::engine_stopped () -{ - ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped) - ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false); - ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); -} - -void -ARDOUR_UI::engine_running () -{ - post_engine(); - - ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true); - ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false); - - Glib::RefPtr action; - const char* action_name = 0; - - switch (engine->samples_per_cycle()) { - case 32: - action_name = X_("JACKLatency32"); - break; - case 64: - action_name = X_("JACKLatency64"); - break; - case 128: - action_name = X_("JACKLatency128"); - break; - case 512: - action_name = X_("JACKLatency512"); - break; - case 1024: - action_name = X_("JACKLatency1024"); - break; - case 2048: - action_name = X_("JACKLatency2048"); - break; - case 4096: - action_name = X_("JACKLatency4096"); - break; - case 8192: - action_name = X_("JACKLatency8192"); - break; - default: - /* XXX can we do anything useful ? */ - break; - } - - if (action_name) { - - action = ActionManager::get_action (X_("JACK"), action_name); - - if (action) { - Glib::RefPtr ract = Glib::RefPtr::cast_dynamic (action); - ract->set_active (); - } - } -} - -void -ARDOUR_UI::engine_halted (const char* reason, bool free_reason) -{ - if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { - /* we can't rely on the original string continuing to exist when we are called - again in the GUI thread, so make a copy and note that we need to - free it later. - */ - char *copy = strdup (reason); - Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true)); - return; - } - - ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false); - ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); - - update_sample_rate (0); - - string msgstr; - - /* if the reason is a non-empty string, it means that the backend was shutdown - rather than just Ardour. - */ - - if (strlen (reason)) { - msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason); - } else { - msgstr = string_compose (_("\ -JACK has either been shutdown or it\n\ -disconnected %1 because %1\n\ -was not fast enough. Try to restart\n\ -JACK, reconnect and save the session."), PROGRAM_NAME); - } - - MessageDialog msg (*editor, msgstr); - pop_back_splash (msg); - msg.set_keep_above (true); - msg.run (); - - if (free_reason) { - free (const_cast (reason)); - } -} - void ARDOUR_UI::update_clocks () { diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 1dcaeb0e9e..e784b5a994 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -315,6 +315,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr NSM_Client *nsm; bool _was_dirty; bool _mixer_on_top; + bool first_time_engine_run; void goto_editor_window (); void goto_mixer_window (); diff --git a/gtk2_ardour/arval b/gtk2_ardour/arval index 6503bc1ede..2209dcb110 100755 --- a/gtk2_ardour/arval +++ b/gtk2_ardour/arval @@ -10,5 +10,6 @@ LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH export ARDOUR_RUNNING_UNDER_VALGRIND=TRUE exec valgrind --tool=memcheck \ $VALGRIND_OPTIONS \ + --track-origins=yes \ --suppressions=`dirname "$0"`/../tools/valgrind.supp \ $TOP/$EXECUTABLE --novst "$@" diff --git a/libs/ardour/ardour/jack_audiobackend.h b/libs/ardour/ardour/jack_audiobackend.h index ada7ce8e33..5ba9ee63d7 100644 --- a/libs/ardour/ardour/jack_audiobackend.h +++ b/libs/ardour/ardour/jack_audiobackend.h @@ -165,14 +165,10 @@ class JACKAudioBackend : public AudioBackend { bool _target_interleaved; uint32_t _target_input_channels; uint32_t _target_output_channels; - uint32_t _target_systemic_input_latency; - uint32_t _target_systemic_output_latency; - - uint32_t _current_sample_rate; - uint32_t _current_buffer_size; - uint32_t _current_usecs_per_cycle; - uint32_t _current_systemic_input_latency; - uint32_t _current_systemic_output_latency; + uint32_t _target_systemic_input_latency; + uint32_t _target_systemic_output_latency; + uint32_t _current_sample_rate; + uint32_t _current_buffer_size; typedef std::set DeviceList; typedef std::map DriverDeviceMap; diff --git a/libs/ardour/ardour/jack_portengine.h b/libs/ardour/ardour/jack_portengine.h index d595b638fa..a267ebb32b 100644 --- a/libs/ardour/ardour/jack_portengine.h +++ b/libs/ardour/ardour/jack_portengine.h @@ -43,6 +43,7 @@ class JACKPortEngine : public PortEngine ~JACKPortEngine(); void* private_handle() const; + bool connected() const; const std::string& my_name() const; diff --git a/libs/ardour/ardour/port_engine.h b/libs/ardour/ardour/port_engine.h index 8e36ad8b09..bb7ec5cb66 100644 --- a/libs/ardour/ardour/port_engine.h +++ b/libs/ardour/ardour/port_engine.h @@ -98,6 +98,8 @@ class PortEngine { */ virtual void* private_handle() const = 0; + virtual bool connected() const = 0; + /** Return the name of this process as used by the port manager * when naming ports. */ diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 9c04529384..2307e9bd52 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -346,8 +346,6 @@ AudioEngine::set_session (Session *s) if (_session) { - start_metering_thread (); - pframes_t blocksize = _backend->buffer_size (); /* page in as much of the session process code as we @@ -567,32 +565,30 @@ AudioEngine::start () _processed_frames = 0; last_monitor_check = 0; - if (_backend->start() == 0) { + if (_backend->start()) { + return -1; + } - _running = true; - last_monitor_check = 0; + _running = true; + + if (_session) { + _session->set_frame_rate (_backend->sample_rate()); - if (_session) { - _session->set_frame_rate (_backend->sample_rate()); - - if (_session->config.get_jack_time_master()) { - _backend->set_time_master (true); - } + if (_session->config.get_jack_time_master()) { + _backend->set_time_master (true); } - - if (!have_ports) { - PortManager::create_ports (); - } - + } + + if (!have_ports) { + PortManager::create_ports (); _mmc.set_ports (mmc_input_port(), mmc_output_port()); - - Running(); /* EMIT SIGNAL */ - - return 0; - } - - /* should report error ... */ - return -1; + } + + start_metering_thread (); + + Running(); /* EMIT SIGNAL */ + + return 0; } int @@ -604,17 +600,18 @@ AudioEngine::stop () Glib::Threads::Mutex::Lock lm (_process_lock); - if (_backend->stop () == 0) { - _running = false; - _processed_frames = 0; - stop_metering_thread (); - - Stopped (); /* EMIT SIGNAL */ - - return 0; + if (_backend->stop ()) { + return -1; } - - return -1; + + _running = false; + _processed_frames = 0; + stop_metering_thread (); + + Port::PortDrop (); + Stopped (); /* EMIT SIGNAL */ + + return 0; } int @@ -624,13 +621,14 @@ AudioEngine::pause () return 0; } - if (_backend->pause () == 0) { - _running = false; - Stopped(); /* EMIT SIGNAL */ - return 0; + if (_backend->pause ()) { + return -1; } - return -1; + _running = false; + + Stopped(); /* EMIT SIGNAL */ + return 0; } int @@ -957,7 +955,9 @@ void AudioEngine::halted_callback (const char* why) { stop_metering_thread (); - Halted (why); /* EMIT SIGNAL */ + + Port::PortDrop (); /* EMIT SIGNAL */ + Halted (why); /* EMIT SIGNAL */ } bool diff --git a/libs/ardour/jack_audiobackend.cc b/libs/ardour/jack_audiobackend.cc index 2e0d90202f..a3bbaecb2d 100644 --- a/libs/ardour/jack_audiobackend.cc +++ b/libs/ardour/jack_audiobackend.cc @@ -40,6 +40,8 @@ using namespace ARDOUR; using namespace PBD; using std::string; using std::vector; +using std::cerr; +using std::endl; #define GET_PRIVATE_JACK_POINTER(localvar) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; } #define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; } @@ -57,6 +59,8 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptrDisconnected.connect_same_thread (disconnect_connection, boost::bind (&JACKAudioBackend::disconnected, this, _1)); } @@ -388,13 +392,13 @@ JACKAudioBackend::output_channels () const uint32_t JACKAudioBackend::systemic_input_latency () const { - return _current_systemic_output_latency; + return _target_systemic_output_latency; } uint32_t JACKAudioBackend::systemic_output_latency () const { - return _current_systemic_output_latency; + return _target_systemic_output_latency; } size_t @@ -455,28 +459,26 @@ JACKAudioBackend::start () setup_jack_startup_command (); } - _jack_connection->open (); - } - - engine.reestablish_ports (); - - if (!jack_port_type_get_buffer_size) { - warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg; + if (_jack_connection->open ()) { + return -1; + } } GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); - engine.sample_rate_change (jack_get_sample_rate (_priv_jack)); + /* get the buffer size and sample rates established */ + + jack_sample_rate_callback (jack_get_sample_rate (_priv_jack)); + jack_bufsize_callback (jack_get_buffer_size (_priv_jack)); - /* testing the nullity of this function name is a proxy for - * whether jack_activate() will definitely call the buffer size - * callback. with older versions of JACK, this function symbol - * will be null. this is sort of reliable, but not clean since - * weak symbol support is highly platform and compiler - * specific. - */ + /* Now that we have buffer size and sample rate established, the engine + can go ahead and do its stuff + */ + + engine.reestablish_ports (); + if (!jack_port_type_get_buffer_size) { - jack_bufsize_callback (jack_get_buffer_size (_priv_jack)); + warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg; } set_jack_callbacks (); @@ -486,7 +488,7 @@ JACKAudioBackend::start () } else { // error << _("cannot activate JACK client") << endmsg; } - + engine.reconnect_ports (); return 0; @@ -869,7 +871,6 @@ JACKAudioBackend::jack_bufsize_callback (pframes_t nframes) GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 1); _current_buffer_size = nframes; - _current_usecs_per_cycle = (int) floor ((((double) nframes / sample_rate())) * 1000000.0); if (jack_port_type_get_buffer_size) { _raw_buffer_sizes[DataType::AUDIO] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_AUDIO_TYPE); diff --git a/libs/ardour/jack_portengine.cc b/libs/ardour/jack_portengine.cc index 82b4502cb6..b0597f8269 100644 --- a/libs/ardour/jack_portengine.cc +++ b/libs/ardour/jack_portengine.cc @@ -124,6 +124,12 @@ JACKPortEngine::private_handle() const return _jack_connection->jack(); } +bool +JACKPortEngine::connected() const +{ + return _jack_connection->connected(); +} + int JACKPortEngine::set_port_name (PortHandle port, const std::string& name) { diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index 6a2636e4f4..bc3a83799b 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -112,7 +112,9 @@ LadspaPlugin::init (void *mod, uint32_t index, framecnt_t rate) port_cnt = parameter_count(); _control_data = new LADSPA_Data[port_cnt]; + memset (_control_data, 0, sizeof (LADSPA_Data) * port_cnt); _shadow_data = new LADSPA_Data[port_cnt]; + memset (_shadow_data, 0, sizeof (LADSPA_Data) * port_cnt); for (i = 0; i < port_cnt; ++i) { if (LADSPA_IS_PORT_CONTROL(port_descriptor (i))) { diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc index 0b0e61000d..d75b861ea1 100644 --- a/libs/ardour/midi_buffer.cc +++ b/libs/ardour/midi_buffer.cc @@ -22,6 +22,7 @@ #include "pbd/malign.h" #include "pbd/compose.h" #include "pbd/debug.h" +#include "pbd/stacktrace.h" #include "ardour/debug.h" #include "ardour/midi_buffer.h" @@ -133,6 +134,7 @@ MidiBuffer::push_back(const Evoral::MIDIEvent& ev) if (_size + stamp_size + ev.size() >= _capacity) { cerr << "MidiBuffer::push_back failed (buffer is full)" << endl; + PBD::stacktrace (cerr, 20); return false; } @@ -171,7 +173,9 @@ MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data) #endif if (_size + stamp_size + size >= _capacity) { - cerr << "MidiBuffer::push_back failed (buffer is full)" << endl; + cerr << "MidiBuffer::push_back2 failed (buffer is full; _size = " << _size << " capacity " + << _capacity << " stamp " << stamp_size << " size = " << size << ")" << endl; + PBD::stacktrace (cerr, 20); return false; } diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index 9191a57080..5589c6e501 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -206,6 +206,7 @@ MidiPort::reset () { Port::reset (); delete _buffer; + cerr << name() << " new MIDI buffer of size " << AudioEngine::instance()->raw_buffer_size (DataType::MIDI) << endl; _buffer = new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)); } diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index 7dc11c6d3d..d37761b6f2 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -88,6 +88,7 @@ void Port::drop () { if (_port_handle) { + DEBUG_TRACE (DEBUG::Ports, string_compose ("drop handle for port %1\n", name())); port_engine.unregister_port (_port_handle); _port_handle = 0; } @@ -120,12 +121,21 @@ Port::disconnect_all () bool Port::connected_to (std::string const & o) const { + if (!port_engine.connected()) { + return false; + } + return port_engine.connected_to (_port_handle, AudioEngine::instance()->make_port_name_non_relative (o)); } int Port::get_connections (std::vector & c) const { + if (!port_engine.connected()) { + c.insert (c.end(), _connections.begin(), _connections.end()); + return c.size(); + } + return port_engine.get_connections (_port_handle, c); } @@ -142,9 +152,9 @@ Port::connect (std::string const & other) } if (sends_output ()) { - port_engine.connect (our_name, other_name); + r = port_engine.connect (our_name, other_name); } else { - port_engine.connect (other_name, our_name); + r = port_engine.connect (other_name, our_name); } if (r == 0) { diff --git a/libs/ardour/port_manager.cc b/libs/ardour/port_manager.cc index 41331fe3a5..4e467e3008 100644 --- a/libs/ardour/port_manager.cc +++ b/libs/ardour/port_manager.cc @@ -439,6 +439,8 @@ PortManager::reestablish_ports () for (i = p->begin(); i != p->end(); ++i) { if (i->second->reestablish ()) { + error << string_compose (_("Re-establising port %1 failed"), i->second->name()) << endmsg; + cerr << string_compose (_("Re-establising port %1 failed"), i->second->name()) << endl; break; } } @@ -458,7 +460,7 @@ PortManager::reconnect_ports () boost::shared_ptr p = ports.reader (); /* re-establish connections */ - + DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size())); for (Ports::iterator i = p->begin(); i != p->end(); ++i) { -- cgit v1.2.3