Add some libardour support for indicating MTC active status.

The general design here is wrong, because it should be more general and cover all possible sync sources.
But it does work, it is used in Tracks, and my attempt to do it correctly revealed the problem to be
an EXTREMELY difficult design issue (as in: two weeks of work on it did not really solve the
fundamental issues with slave design).

So, here it is for now, c/o Grygorii
This commit is contained in:
Paul Davis 2015-05-12 12:17:17 -04:00
parent 5c8c249db9
commit 16dccfcb8a
5 changed files with 63 additions and 26 deletions

View File

@ -297,6 +297,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
PBD::Signal0<void> IOConnectionsComplete;
/* Timecode status signals */
PBD::Signal1<void, bool> MTCSyncStateChanged;
/* Record status signals */
PBD::Signal0<void> RecordStateChanged; /* signals changes in recording state (i.e. are we recording) */
@ -343,6 +346,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
/* Step Editing status changed */
PBD::Signal1<void,bool> StepEditStatusChange;
/* Timecode state signals */
PBD::Signal0<void> MtcOrLtcInputPortChanged;
void queue_event (SessionEvent*);
void request_roll_at_and_return (framepos_t start, framepos_t return_to);
@ -600,7 +606,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
void request_sync_source (Slave*);
bool synced_to_engine() const { return _slave && config.get_external_sync() && Config->get_sync_source() == Engine; }
bool synced_to_mtc () const { return config.get_external_sync() && Config->get_sync_source() == MTC && g_atomic_int_get (const_cast<gint*>(&_mtc_active)); }
double transport_speed() const { return _transport_speed; }
bool transport_stopped() const { return _transport_speed == 0.0f; }
bool transport_rolling() const { return _transport_speed != 0.0f; }
@ -1070,6 +1077,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
bool _under_nsm_control;
unsigned int _xrun_count;
void mtc_status_changed (bool);
PBD::ScopedConnection mtc_status_connection;
void initialize_latencies ();
void set_worst_io_latencies ();
void set_worst_playback_latency ();
@ -1107,6 +1117,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
bool have_first_delta_accumulator;
SlaveState _slave_state;
gint _mtc_active;
framepos_t slave_wait_end;
void reset_slave_state ();

View File

@ -273,6 +273,8 @@ class LIBARDOUR_API MTC_Slave : public TimecodeSlave {
std::string approximate_current_position() const;
std::string approximate_current_delta() const;
PBD::Signal1<void, bool> ActiveChanged;
private:
Session& session;
MidiPort* port;

View File

@ -213,6 +213,7 @@ MTC_Slave::reset (bool with_position)
window_end = 0;
transport_direction = 1;
current_delta = 0;
ActiveChanged(false);
}
void
@ -468,6 +469,7 @@ MTC_Slave::update_mtc_time (const MIDI::byte *msg, bool was_full, framepos_t now
first_mtc_timestamp = now;
init_mtc_dll(mtc_frame, qtr);
mtc_frame_dll = mtc_frame;
ActiveChanged (true); // emit signal
}
current.guard1++;
current.position = mtc_frame;
@ -626,6 +628,7 @@ MTC_Slave::speed_and_position (double& speed, framepos_t& pos)
session.request_transport_speed (0);
engine_dll_initstate = 0;
queue_reset (false);
ActiveChanged (false);
DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 2 frames - reset pending\n");
return false;
}

View File

@ -184,6 +184,7 @@ Session::Session (AudioEngine &eng,
, average_dir (0)
, have_first_delta_accumulator (false)
, _slave_state (Stopped)
, _mtc_active (false)
, post_export_sync (false)
, post_export_position (0)
, _exporting (false)
@ -2671,36 +2672,37 @@ Session::reconnect_midi_scene_ports(bool inputs)
}
void
Session::reconnect_mtc_ports()
Session::reconnect_mtc_ports ()
{
#if 0
boost::shared_ptr<MidiPort> mtc_in_ptr = _midi_ports->mtc_input_port();
if (mtc_in_ptr) {
mtc_in_ptr->disconnect_all ();
std::vector<EngineStateController::MidiPortState> midi_port_states;
EngineStateController::instance()->get_physical_midi_input_states (midi_port_states);
std::vector<EngineStateController::MidiPortState>::iterator state_iter = midi_port_states.begin();
for (; state_iter != midi_port_states.end(); ++state_iter) {
if (state_iter->available && state_iter->mtc_in) {
mtc_in_ptr->connect (state_iter->name);
}
}
if (!_midi_ports->mtc_input_port ()->connected () &&
config.get_external_sync () &&
(Config->get_sync_source () == MTC) ) {
config.set_external_sync (false);
}
if ( ARDOUR::Profile->get_trx () ) {
// Tracks need this signal to update timecode_source_dropdown
MtcOrLtcInputPortChanged (); //emit signal
if (!mtc_in_ptr) {
return;
}
mtc_in_ptr->disconnect_all ();
std::vector<EngineStateController::MidiPortState> midi_port_states;
EngineStateController::instance()->get_physical_midi_input_states (midi_port_states);
std::vector<EngineStateController::MidiPortState>::iterator state_iter = midi_port_states.begin();
for (; state_iter != midi_port_states.end(); ++state_iter) {
if (state_iter->available && state_iter->mtc_in) {
mtc_in_ptr->connect (state_iter->name);
}
}
#endif
if (!_midi_ports->mtc_input_port ()->connected () &&
config.get_external_sync () &&
(Config->get_sync_source () == MTC) ) {
config.set_external_sync (false);
}
if ( ARDOUR::Profile->get_trx () ) {
// Tracks need this signal to update timecode_source_dropdown
MtcOrLtcInputPortChanged (); //emit signal
}
}
void

View File

@ -1542,6 +1542,13 @@ Session::reset_rf_scale (framecnt_t motion)
}
}
void
Session::mtc_status_changed (bool yn)
{
g_atomic_int_set (&_mtc_active, yn);
MTCSyncStateChanged( yn );
}
void
Session::use_sync_source (Slave* new_slave)
{
@ -1554,6 +1561,18 @@ Session::use_sync_source (Slave* new_slave)
delete _slave;
_slave = new_slave;
MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
if (mtc_slave) {
mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
MTCSyncStateChanged(mtc_slave->locked() );
} else {
if (g_atomic_int_get (&_mtc_active) ){
g_atomic_int_set (&_mtc_active, 0);
MTCSyncStateChanged( false );
}
mtc_status_connection.disconnect ();
}
DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
// need to queue this for next process() cycle