summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2019-01-24 22:05:20 -0700
committerPaul Davis <paul@linuxaudiosystems.com>2019-01-25 09:23:08 -0700
commit1be3301342c74fdbb92febcbc85e8d60fb09de0e (patch)
tree4fbdc594951ed02e89c0b47e10ccaae75e9b69fd /libs
parentc01ab83e1f13f6d56a2e8ec13e9d26683dc9bb25 (diff)
new approach to handling Transport Masters when engine is restarted
Trust that ::reset() works for all transport masters, and call it when engine is stopped. This way the transport masters are ready to be called again as soon as the engine restarts.
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/transport_master.h17
-rw-r--r--libs/ardour/ardour/transport_master_manager.h2
-rw-r--r--libs/ardour/audioengine.cc2
-rw-r--r--libs/ardour/engine_slave.cc6
-rw-r--r--libs/ardour/globals.cc37
-rw-r--r--libs/ardour/ltc_slave.cc12
-rw-r--r--libs/ardour/midi_clock_slave.cc20
-rw-r--r--libs/ardour/mtc_slave.cc7
-rw-r--r--libs/ardour/session_ltc.cc7
-rw-r--r--libs/ardour/session_process.cc1
-rw-r--r--libs/ardour/session_state.cc1
-rw-r--r--libs/ardour/session_transport.cc2
-rw-r--r--libs/ardour/transport_master.cc15
-rw-r--r--libs/ardour/transport_master_manager.cc60
14 files changed, 139 insertions, 50 deletions
diff --git a/libs/ardour/ardour/transport_master.h b/libs/ardour/ardour/transport_master.h
index c70757647b..98f8efae88 100644
--- a/libs/ardour/ardour/transport_master.h
+++ b/libs/ardour/ardour/transport_master.h
@@ -33,7 +33,7 @@
#include "pbd/i18n.h"
#include "pbd/properties.h"
#include "pbd/signals.h"
-#include "pbd/stateful.h"
+#include "pbd/statefuldestructible.h"
#include "temporal/time.h"
@@ -214,6 +214,8 @@ class LIBARDOUR_API TransportMaster : public PBD::Stateful {
*/
virtual bool speed_and_position (double& speed, samplepos_t& position, samplepos_t & lp, samplepos_t & when, samplepos_t now);
+ virtual void reset (bool with_position) = 0;
+
/**
* reports to ARDOUR whether the TransportMaster is currently synced to its external
* time source.
@@ -346,6 +348,8 @@ class LIBARDOUR_API TransportMaster : public PBD::Stateful {
std::string display_name (bool sh/*ort*/ = true) const;
+ virtual void unregister_port ();
+
protected:
SyncSource _type;
PBD::Property<std::string> _name;
@@ -423,6 +427,9 @@ class LIBARDOUR_API MTC_TransportMaster : public TimecodeTransportMaster, public
void pre_process (pframes_t nframes, samplepos_t now, boost::optional<samplepos_t>);
+ void unregister_port ();
+
+ void reset (bool with_pos);
bool locked() const;
bool ok() const;
void handle_locate (const MIDI::byte*);
@@ -467,7 +474,6 @@ class LIBARDOUR_API MTC_TransportMaster : public TimecodeTransportMaster, public
Timecode::Time timecode;
bool printed_timecode_warning;
- void reset (bool with_pos);
void queue_reset (bool with_pos);
void maybe_reset ();
@@ -490,6 +496,7 @@ public:
void pre_process (pframes_t nframes, samplepos_t now, boost::optional<samplepos_t>);
+ void reset (bool with_pos);
bool locked() const;
bool ok() const;
@@ -510,7 +517,6 @@ public:
bool detect_discontinuity(LTCFrameExt *, int, bool);
bool detect_ltc_fps(int, bool);
bool equal_ltc_sample_time(LTCFrame *a, LTCFrame *b);
- void reset (bool with_ts = true);
void resync_xrun();
void resync_latency();
void parse_timecode_offset();
@@ -550,10 +556,13 @@ class LIBARDOUR_API MIDIClock_TransportMaster : public TransportMaster, public T
void set_session (Session*);
+ void unregister_port ();
+
void pre_process (pframes_t nframes, samplepos_t now, boost::optional<samplepos_t>);
void rebind (MidiPort&);
+ void reset (bool with_pos);
bool locked() const;
bool ok() const;
bool starting() const;
@@ -594,7 +603,6 @@ class LIBARDOUR_API MIDIClock_TransportMaster : public TransportMaster, public T
bool _running;
double _bpm;
- void reset ();
void start (MIDI::Parser& parser, samplepos_t timestamp);
void contineu (MIDI::Parser& parser, samplepos_t timestamp);
void stop (MIDI::Parser& parser, samplepos_t timestamp);
@@ -616,6 +624,7 @@ class LIBARDOUR_API Engine_TransportMaster : public TransportMaster
bool speed_and_position (double& speed, samplepos_t& pos, samplepos_t &, samplepos_t &, samplepos_t);
bool starting() const { return _starting; }
+ void reset (bool with_position);
bool locked() const;
bool ok() const;
samplecnt_t update_interval () const;
diff --git a/libs/ardour/ardour/transport_master_manager.h b/libs/ardour/ardour/transport_master_manager.h
index ac61a97a9f..b0de99619a 100644
--- a/libs/ardour/ardour/transport_master_manager.h
+++ b/libs/ardour/ardour/transport_master_manager.h
@@ -36,6 +36,8 @@ class LIBARDOUR_API TransportMasterManager : public boost::noncopyable
~TransportMasterManager ();
int set_default_configuration ();
+ void restart ();
+ void engine_stopped ();
static TransportMasterManager& instance();
/* this method is not thread-safe and is intended to be used only
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 5e9948ef8d..3fbc7635e1 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -1002,6 +1002,8 @@ AudioEngine::stop (bool for_latency)
}
if (stop_engine) {
+ TransportMasterManager& tmm (TransportMasterManager::instance());
+ tmm.engine_stopped ();
Stopped (); /* EMIT SIGNAL */
}
diff --git a/libs/ardour/engine_slave.cc b/libs/ardour/engine_slave.cc
index 451356536a..870b2a1757 100644
--- a/libs/ardour/engine_slave.cc
+++ b/libs/ardour/engine_slave.cc
@@ -57,6 +57,12 @@ Engine_TransportMaster::check_backend()
}
}
+void
+Engine_TransportMaster::reset (bool)
+{
+ _starting = false;
+}
+
bool
Engine_TransportMaster::locked() const
{
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index b40db9466c..665277388a 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -561,7 +561,7 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
ARDOUR::AudioEngine::create ();
- /* This will run only once in whatever thread calls AudioEngine::start() */
+ /* This will run in whatever thread calls AudioEngine::start() */
ARDOUR::AudioEngine::instance()->Running.connect_same_thread (engine_startup_connection, ARDOUR::init_post_engine);
/* it is unfortunate that we need to include reserved names here that
@@ -599,39 +599,30 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
}
void
-ARDOUR::init_post_engine (uint32_t /* ignored */)
+ARDOUR::init_post_engine (uint32_t start_cnt)
{
XMLNode* node;
- if ((node = Config->control_protocol_state()) != 0) {
- ControlProtocolManager::instance().set_state (*node, 0 /* here: global-config state */);
- }
+ std::cerr << "Engine stated, libardour inits, cnt = " << start_cnt << std::endl;
- if ((node = Config->transport_master_state()) != 0) {
- if (TransportMasterManager::instance().set_state (*node, Stateful::loading_state_version)) {
- error << _("Cannot restore transport master manager") << endmsg;
- /* XXX now what? */
- }
- } else {
- if (TransportMasterManager::instance().set_default_configuration ()) {
- error << _("Cannot initialize transport master manager") << endmsg;
- /* XXX now what? */
- }
- }
+ if (start_cnt == 0) {
- /* find plugins */
+ /* find plugins */
- ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
+ ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
+ }
- /* Don't do this again - we are only meant to execute on the first
- * engine start, not any subsequence starts
- */
+ if ((node = Config->control_protocol_state()) != 0) {
+ ControlProtocolManager::instance().set_state (*node, 0 /* here: global-config state */);
+ }
- engine_startup_connection.disconnect ();
+ if (start_cnt == 0) {
+ TransportMasterManager::instance().restart ();
+ }
}
void
- ARDOUR::cleanup ()
+ARDOUR::cleanup ()
{
if (!libardour_initialized) {
return;
diff --git a/libs/ardour/ltc_slave.cc b/libs/ardour/ltc_slave.cc
index 9f8411103f..9fe2635446 100644
--- a/libs/ardour/ltc_slave.cc
+++ b/libs/ardour/ltc_slave.cc
@@ -104,7 +104,7 @@ LTC_TransportMaster::set_session (Session *s)
decoder = ltc_decoder_create((int) samples_per_ltc_frame, 128 /*queue size*/);
parse_timecode_offset();
- reset();
+ reset (true);
_session->config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&LTC_TransportMaster::parameter_changed, this, _1));
}
@@ -189,10 +189,10 @@ LTC_TransportMaster::resync_latency()
}
void
-LTC_TransportMaster::reset (bool with_ts)
+LTC_TransportMaster::reset (bool with_position)
{
DEBUG_TRACE (DEBUG::LTC, "LTC reset()\n");
- if (with_ts) {
+ if (with_position) {
current.update (current.position, 0, current.speed);
_current_delta = 0;
}
@@ -381,7 +381,7 @@ LTC_TransportMaster::process_ltc(samplepos_t const now)
}
if (!ltc_is_stationary && detect_ltc_fps (stime.frame, (sample.ltc.dfbit)? true : false)) {
- reset();
+ reset(true);
fps_detected=true;
}
@@ -528,7 +528,7 @@ LTC_TransportMaster::pre_process (ARDOUR::pframes_t nframes, samplepos_t now, bo
} else if (skip != 0) {
/* this should never happen. it may if monotonic_cnt, now overflow on 64bit */
DEBUG_TRACE (DEBUG::LTC, string_compose("engine skipped %1 samples\n", skip));
- reset();
+ reset(true);
}
/* Now feed the incoming LTC signal into the decoder */
@@ -553,7 +553,7 @@ LTC_TransportMaster::pre_process (ARDOUR::pframes_t nframes, samplepos_t now, bo
if (abs (now - current.timestamp) > FLYWHEEL_TIMEOUT) {
DEBUG_TRACE (DEBUG::LTC, "flywheel timeout\n");
- reset();
+ reset(true);
/* don't change position from last known */
return;
diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc
index 706032887d..a6d0af2c1f 100644
--- a/libs/ardour/midi_clock_slave.cc
+++ b/libs/ardour/midi_clock_slave.cc
@@ -88,7 +88,7 @@ MIDIClock_TransportMaster::set_session (Session *session)
parser.stop.connect_same_thread (port_connections, boost::bind (&MIDIClock_TransportMaster::stop, this, _1, _2));
parser.position.connect_same_thread (port_connections, boost::bind (&MIDIClock_TransportMaster::position, this, _1, _2, _3, _4));
- reset ();
+ reset (true);
}
}
@@ -284,18 +284,22 @@ MIDIClock_TransportMaster::start (Parser& /*parser*/, samplepos_t timestamp)
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_TransportMaster got start message at time %1 engine time %2 transport_sample %3\n", timestamp, ENGINE->sample_time(), _session->transport_sample()));
if (!_running) {
- reset();
+ reset(true);
_running = true;
current.update (_session->transport_sample(), timestamp, 0);
}
}
void
-MIDIClock_TransportMaster::reset ()
+MIDIClock_TransportMaster::reset (bool with_position)
{
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MidiClock Master reset(): calculated filter for period size %2\n", ENGINE->samples_per_cycle()));
- current.update (_session->transport_sample(), 0, 0);
+ if (with_position) {
+ current.update (_session->transport_sample(), 0, 0);
+ } else {
+ current.update (0, 0, 0);
+ }
_running = false;
_current_delta = 0;
@@ -409,3 +413,11 @@ MIDIClock_TransportMaster::delta_string() const
}
return std::string(delta);
}
+
+void
+MIDIClock_TransportMaster::unregister_port ()
+{
+ _midi_port.reset ();
+ TransportMaster::unregister_port ();
+}
+
diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc
index f8afe66d93..28a51f96e7 100644
--- a/libs/ardour/mtc_slave.cc
+++ b/libs/ardour/mtc_slave.cc
@@ -587,3 +587,10 @@ MTC_TransportMaster::delta_string () const
}
return std::string(delta);
}
+
+void
+MTC_TransportMaster::unregister_port ()
+{
+ _midi_port.reset ();
+ TransportMaster::unregister_port ();
+}
diff --git a/libs/ardour/session_ltc.cc b/libs/ardour/session_ltc.cc
index c2cd0ef681..094b502d52 100644
--- a/libs/ardour/session_ltc.cc
+++ b/libs/ardour/session_ltc.cc
@@ -184,7 +184,12 @@ Session::ltc_tx_send_time_code_for_cycle (samplepos_t start_sample, samplepos_t
return;
}
+ if (!TransportMasterManager::instance().current()) {
+ return;
+ }
+
SyncSource sync_src = TransportMasterManager::instance().current()->type();
+
if (engine().freewheeling() || !Config->get_send_ltc()
/* TODO
* decide which time-sources we can generated LTC from.
@@ -194,7 +199,7 @@ Session::ltc_tx_send_time_code_for_cycle (samplepos_t start_sample, samplepos_t
|| (config.get_external_sync() && sync_src == LTC)
|| (config.get_external_sync() && sync_src == MTC)
*/
- ||(config.get_external_sync() && sync_src == MIDIClock)
+ ||(config.get_external_sync() && sync_src == MIDIClock)
) {
return;
}
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 1cc9a03e02..bece787fd7 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -861,6 +861,7 @@ Session::process_event (SessionEvent* ev)
break;
case SessionEvent::SetTransportMaster:
+ cerr << "Process TMM current request\n";
TransportMasterManager::instance().set_current (ev->transport_master);
break;
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 8809ab388c..a8f9d6022f 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -4098,6 +4098,7 @@ Session::config_changed (std::string p, bool ours)
first_file_data_format_reset = false;
} else if (p == "external-sync") {
+ std::cerr << "param change, rss to " << TransportMasterManager::instance().current() << std::endl;
request_sync_source (TransportMasterManager::instance().current());
} else if (p == "denormal-model") {
setup_fpu ();
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index a79de32c1e..7fe8f15e61 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -1975,7 +1975,7 @@ Session::transport_master() const
bool
Session::transport_master_is_external () const
{
- return config.get_external_sync();
+ return TransportMasterManager::instance().current() && config.get_external_sync();
}
void
diff --git a/libs/ardour/transport_master.cc b/libs/ardour/transport_master.cc
index 2564f87c5d..8799d51486 100644
--- a/libs/ardour/transport_master.cc
+++ b/libs/ardour/transport_master.cc
@@ -19,7 +19,9 @@
#include <vector>
+#include "pbd/boost_debug.h"
#include "pbd/debug.h"
+#include "pbd/i18n.h"
#include "ardour/audioengine.h"
#include "ardour/debug.h"
@@ -30,7 +32,6 @@
#include "ardour/types_convert.h"
#include "ardour/utils.h"
-#include "pbd/i18n.h"
namespace ARDOUR {
namespace Properties {
@@ -83,6 +84,9 @@ TransportMaster::TransportMaster (SyncSource t, std::string const & name)
TransportMaster::~TransportMaster()
{
+ DEBUG_TRACE (DEBUG::Destruction, string_compose ("destroying transport master \"%1\" along with port %2\n", name(), (_port ? _port->name() : std::string ("no port"))));
+
+ unregister_port ();
}
bool
@@ -431,6 +435,15 @@ TransportMaster::display_name (bool sh) const
return S_("SyncSource|JACK");
}
+void
+TransportMaster::unregister_port ()
+{
+ if (_port) {
+ AudioEngine::instance()->unregister_port (_port);
+ _port.reset ();
+ }
+}
+
boost::shared_ptr<Port>
TransportMasterViaMIDI::create_midi_port (std::string const & port_name)
{
diff --git a/libs/ardour/transport_master_manager.cc b/libs/ardour/transport_master_manager.cc
index fafbf6042b..508d677a8a 100644
--- a/libs/ardour/transport_master_manager.cc
+++ b/libs/ardour/transport_master_manager.cc
@@ -22,6 +22,7 @@
#include "ardour/session.h"
#include "ardour/transport_master_manager.h"
+#include "pbd/boost_debug.cc"
#include "pbd/i18n.h"
#if __cplusplus > 199711L
@@ -54,19 +55,24 @@ int
TransportMasterManager::set_default_configuration ()
{
try {
+
+ clear ();
+
/* setup default transport masters. Most people will never need any
others
*/
+
add (Engine, X_("JACK Transport"), false);
add (MTC, X_("MTC"), false);
add (LTC, X_("LTC"), false);
add (MIDIClock, X_("MIDI Clock"), false);
+
} catch (...) {
return -1;
}
_current_master = _transport_masters.back();
-
+ cerr << "default current master (back) is " << _current_master->name() << endl;
return 0;
}
@@ -324,6 +330,7 @@ TransportMasterManager::add (SyncSource type, std::string const & name, bool rem
}
tm = TransportMaster::factory (type, name, removeable);
+ boost_debug_shared_ptr_mark_interesting (tm.get(), "tm");
ret = add_locked (tm);
}
@@ -382,9 +389,11 @@ TransportMasterManager::remove (std::string const & name)
int
TransportMasterManager::set_current_locked (boost::shared_ptr<TransportMaster> c)
{
- if (find (_transport_masters.begin(), _transport_masters.end(), c) == _transport_masters.end()) {
- warning << string_compose (X_("programming error: attempt to use unknown transport master named \"%1\"\n"), c->name());
- return -1;
+ if (c) {
+ if (find (_transport_masters.begin(), _transport_masters.end(), c) == _transport_masters.end()) {
+ warning << string_compose (X_("programming error: attempt to use unknown transport master \"%1\"\n"), c->name());
+ return -1;
+ }
}
_current_master = c;
@@ -393,7 +402,7 @@ TransportMasterManager::set_current_locked (boost::shared_ptr<TransportMaster> c
master_dll_initstate = 0;
- DEBUG_TRACE (DEBUG::Slave, string_compose ("current transport master set to %1\n", c->name()));
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("current transport master set to %1\n", (c ? c->name() : string ("none"))));
return 0;
}
@@ -471,6 +480,7 @@ TransportMasterManager::clear ()
{
{
Glib::Threads::RWLock::WriterLock lm (lock);
+ _current_master.reset ();
_transport_masters.clear ();
}
@@ -484,18 +494,18 @@ TransportMasterManager::set_state (XMLNode const & node, int version)
XMLNodeList const & children = node.children();
-
- if (!children.empty()) {
- _transport_masters.clear ();
- }
-
{
Glib::Threads::RWLock::WriterLock lm (lock);
+ _current_master.reset ();
+ boost_debug_list_ptrs ();
+
+ _transport_masters.clear ();
for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
boost::shared_ptr<TransportMaster> tm = TransportMaster::factory (**c);
+ boost_debug_shared_ptr_mark_interesting (tm.get(), "tm");
if (add_locked (tm)) {
continue;
@@ -548,3 +558,33 @@ TransportMasterManager::master_by_type (SyncSource src) const
return boost::shared_ptr<TransportMaster> ();
}
+
+void
+TransportMasterManager::engine_stopped ()
+{
+ {
+ Glib::Threads::RWLock::ReaderLock lm (lock);
+
+ for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
+ (*tm)->reset (false);
+ }
+ }
+}
+
+void
+TransportMasterManager::restart ()
+{
+ XMLNode* node;
+
+ if ((node = Config->transport_master_state()) != 0) {
+ if (TransportMasterManager::instance().set_state (*node, Stateful::loading_state_version)) {
+ error << _("Cannot restore transport master manager") << endmsg;
+ /* XXX now what? */
+ }
+ } else {
+ if (TransportMasterManager::instance().set_default_configuration ()) {
+ error << _("Cannot initialize transport master manager") << endmsg;
+ /* XXX now what? */
+ }
+ }
+}