Set timecode format from active master only
This commit is contained in:
parent
5120b650c5
commit
7289be59c9
|
@ -474,8 +474,10 @@ public:
|
|||
TimecodeTransportMaster (std::string const& name, SyncSource type);
|
||||
|
||||
virtual Timecode::TimecodeFormat apparent_timecode_format () const = 0;
|
||||
samplepos_t timecode_offset;
|
||||
bool timecode_negative_offset;
|
||||
|
||||
bool apparent_timecode_format_valid () const {
|
||||
return timecode_format_valid;
|
||||
}
|
||||
|
||||
bool fr2997 () const
|
||||
{
|
||||
|
@ -486,6 +488,10 @@ public:
|
|||
protected:
|
||||
void register_properties ();
|
||||
|
||||
samplepos_t timecode_offset;
|
||||
bool timecode_negative_offset;
|
||||
bool timecode_format_valid;
|
||||
|
||||
private:
|
||||
PBD::Property<bool> _fr2997;
|
||||
};
|
||||
|
@ -536,8 +542,7 @@ private:
|
|||
samplepos_t window_begin;
|
||||
samplepos_t window_end;
|
||||
samplepos_t first_mtc_timestamp;
|
||||
bool did_reset_tc_format;
|
||||
Timecode::TimecodeFormat saved_tc_format;
|
||||
|
||||
Glib::Threads::Mutex reset_lock;
|
||||
uint32_t reset_pending;
|
||||
bool reset_position;
|
||||
|
@ -545,12 +550,9 @@ private:
|
|||
int busy_guard1;
|
||||
int busy_guard2;
|
||||
|
||||
double speedup_due_to_tc_mismatch;
|
||||
double quarter_frame_duration;
|
||||
Timecode::TimecodeFormat mtc_timecode;
|
||||
Timecode::TimecodeFormat a3e_timecode;
|
||||
Timecode::Time timecode;
|
||||
bool printed_timecode_warning;
|
||||
|
||||
void queue_reset (bool with_pos);
|
||||
void maybe_reset ();
|
||||
|
@ -616,26 +618,20 @@ private:
|
|||
void parameter_changed (std::string const& p);
|
||||
void connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string, boost::weak_ptr<ARDOUR::Port>, std::string, bool);
|
||||
|
||||
bool did_reset_tc_format;
|
||||
Timecode::TimecodeFormat saved_tc_format;
|
||||
|
||||
LTCDecoder* decoder;
|
||||
double samples_per_ltc_frame;
|
||||
Timecode::Time timecode;
|
||||
LTCFrameExt prev_frame;
|
||||
bool fps_detected;
|
||||
|
||||
samplecnt_t monotonic_cnt;
|
||||
uint64_t frames_since_reset;
|
||||
int delayedlocked;
|
||||
samplecnt_t monotonic_cnt;
|
||||
uint64_t frames_since_reset;
|
||||
int delayedlocked;
|
||||
|
||||
int ltc_detect_fps_cnt;
|
||||
int ltc_detect_fps_max;
|
||||
bool printed_timecode_warning;
|
||||
bool sync_lock_broken;
|
||||
Timecode::TimecodeFormat ltc_timecode;
|
||||
Timecode::TimecodeFormat a3e_timecode;
|
||||
double samples_per_timecode_frame;
|
||||
int ltc_detect_fps_cnt;
|
||||
int ltc_detect_fps_max;
|
||||
bool sync_lock_broken;
|
||||
double samples_per_timecode_frame;
|
||||
|
||||
PBD::ScopedConnection port_connection;
|
||||
PBD::ScopedConnectionList session_connections;
|
||||
|
|
|
@ -96,26 +96,32 @@ class LIBARDOUR_API TransportMasterManager : public boost::noncopyable
|
|||
mutable Glib::Threads::RWLock lock;
|
||||
double _master_speed;
|
||||
samplepos_t _master_position;
|
||||
boost::shared_ptr<TransportMaster> _current_master;
|
||||
|
||||
boost::shared_ptr<TransportMaster> _current_master;
|
||||
Session* _session;
|
||||
|
||||
bool _master_invalid_this_cycle;
|
||||
bool disk_output_blocked;
|
||||
|
||||
// a DLL to chase the transport master
|
||||
|
||||
int transport_dll_initstate;
|
||||
double t0; /// time at the beginning of ???
|
||||
double t1; /// calculated end of the ???
|
||||
double e2; /// second order loop error
|
||||
double bandwidth; /// DLL filter bandwidth
|
||||
double b, c, omega; /// DLL filter coefficients
|
||||
/* a DLL to chase the transport master, calculate playback speed
|
||||
* by matching Ardour's current playhead position against
|
||||
* the position of the transport-master */
|
||||
double t0; // PH position at the beginning of this cycle
|
||||
double t1; // expected PH position if next cycle
|
||||
double e2; // second order loop error
|
||||
double bandwidth; // DLL filter bandwidth
|
||||
double b, c, omega; // DLL filter coefficients
|
||||
|
||||
void init_transport_master_dll (double speed, samplepos_t pos);
|
||||
int master_dll_initstate;
|
||||
int master_dll_initstate; // play-direction -1, +1, or 0: not initialized
|
||||
|
||||
static TransportMasterManager* _instance;
|
||||
|
||||
/* original TC format in case the slave changed it */
|
||||
boost::optional<Timecode::TimecodeFormat> _session_tc_format;
|
||||
void maybe_restore_tc_format ();
|
||||
void maybe_set_tc_format ();
|
||||
|
||||
int add_locked (boost::shared_ptr<TransportMaster>);
|
||||
double compute_matching_master_speed (pframes_t nframes, samplepos_t, bool& locate_required);
|
||||
int set_current_locked (boost::shared_ptr<TransportMaster>);
|
||||
|
|
|
@ -48,8 +48,6 @@ using namespace Timecode;
|
|||
|
||||
LTC_TransportMaster::LTC_TransportMaster (std::string const & name)
|
||||
: TimecodeTransportMaster (name, LTC)
|
||||
, did_reset_tc_format (false)
|
||||
, saved_tc_format (timecode_24) // whatever ....
|
||||
, decoder (0)
|
||||
, samples_per_ltc_frame (0)
|
||||
, fps_detected (false)
|
||||
|
@ -58,10 +56,7 @@ LTC_TransportMaster::LTC_TransportMaster (std::string const & name)
|
|||
, delayedlocked (10)
|
||||
, ltc_detect_fps_cnt (0)
|
||||
, ltc_detect_fps_max (0)
|
||||
, printed_timecode_warning (false)
|
||||
, sync_lock_broken (false)
|
||||
, ltc_timecode (Timecode::timecode_24)
|
||||
, a3e_timecode (Timecode::timecode_24)
|
||||
, samples_per_timecode_frame (0)
|
||||
{
|
||||
memset (&prev_frame, 0, sizeof(LTCFrameExt));
|
||||
|
@ -94,9 +89,6 @@ LTC_TransportMaster::set_session (Session *s)
|
|||
|
||||
samples_per_ltc_frame = _session->samples_per_timecode_frame();
|
||||
timecode.drop = _session->timecode_drop_frames();
|
||||
printed_timecode_warning = false;
|
||||
ltc_timecode = _session->config.get_timecode_format();
|
||||
a3e_timecode = _session->config.get_timecode_format();
|
||||
|
||||
if (decoder) {
|
||||
ltc_decoder_free (decoder);
|
||||
|
@ -117,10 +109,6 @@ LTC_TransportMaster::~LTC_TransportMaster()
|
|||
port_connection.disconnect();
|
||||
session_connections.drop_connections();
|
||||
|
||||
if (did_reset_tc_format) {
|
||||
_session->config.set_timecode_format (saved_tc_format);
|
||||
}
|
||||
|
||||
ltc_decoder_free(decoder);
|
||||
}
|
||||
|
||||
|
@ -234,6 +222,7 @@ LTC_TransportMaster::reset (bool with_position)
|
|||
monotonic_cnt = 0;
|
||||
memset (&prev_frame, 0, sizeof(LTCFrameExt));
|
||||
frames_since_reset = 0;
|
||||
timecode_format_valid = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -358,6 +347,8 @@ LTC_TransportMaster::detect_ltc_fps(int frameno, bool df)
|
|||
}
|
||||
}
|
||||
|
||||
timecode_format_valid = true; /* SET FLAG */
|
||||
|
||||
if (timecode.rate != detected_fps || timecode.drop != df) {
|
||||
DEBUG_TRACE (DEBUG::LTC, string_compose ("detected FPS: %1%2\n", detected_fps, df?"df":"ndf"));
|
||||
} else {
|
||||
|
@ -378,50 +369,7 @@ LTC_TransportMaster::detect_ltc_fps(int frameno, bool df)
|
|||
}
|
||||
|
||||
TimecodeFormat tc_format = apparent_timecode_format();
|
||||
|
||||
if (_session) {
|
||||
|
||||
/* poll and check session TC */
|
||||
|
||||
TimecodeFormat cur_timecode = _session->config.get_timecode_format();
|
||||
|
||||
if (Config->get_timecode_sync_frame_rate()) {
|
||||
/* enforce time-code */
|
||||
if (!did_reset_tc_format) {
|
||||
saved_tc_format = cur_timecode;
|
||||
did_reset_tc_format = true;
|
||||
}
|
||||
if (cur_timecode != tc_format) {
|
||||
if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) {
|
||||
warning << string_compose(_("Session framerate adjusted from %1 to LTC's %2."),
|
||||
Timecode::timecode_format_name(cur_timecode),
|
||||
Timecode::timecode_format_name(tc_format))
|
||||
<< endmsg;
|
||||
}
|
||||
_session->config.set_timecode_format (tc_format);
|
||||
}
|
||||
} else {
|
||||
/* only warn about TC mismatch */
|
||||
if (ltc_timecode != tc_format) printed_timecode_warning = false;
|
||||
if (a3e_timecode != cur_timecode) printed_timecode_warning = false;
|
||||
|
||||
if (cur_timecode != tc_format && ! printed_timecode_warning) {
|
||||
if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) {
|
||||
warning << string_compose(_("Session and LTC framerate mismatch: LTC:%1 Session:%2."),
|
||||
Timecode::timecode_format_name(tc_format),
|
||||
Timecode::timecode_format_name(cur_timecode))
|
||||
<< endmsg;
|
||||
}
|
||||
printed_timecode_warning = true;
|
||||
}
|
||||
}
|
||||
|
||||
a3e_timecode = cur_timecode;
|
||||
}
|
||||
|
||||
ltc_timecode = tc_format;
|
||||
|
||||
samples_per_timecode_frame = ENGINE->sample_rate() / Timecode::timecode_to_frames_per_second (ltc_timecode);
|
||||
samples_per_timecode_frame = ENGINE->sample_rate() / Timecode::timecode_to_frames_per_second (tc_format);
|
||||
|
||||
return fps_changed;
|
||||
}
|
||||
|
|
|
@ -61,13 +61,11 @@ MTC_TransportMaster::MTC_TransportMaster (std::string const & name)
|
|||
, window_begin (0)
|
||||
, window_end (0)
|
||||
, first_mtc_timestamp (0)
|
||||
, did_reset_tc_format (false)
|
||||
, reset_pending (0)
|
||||
, reset_position (false)
|
||||
, transport_direction (1)
|
||||
, busy_guard1 (0)
|
||||
, busy_guard2 (0)
|
||||
, printed_timecode_warning (false)
|
||||
{
|
||||
init ();
|
||||
}
|
||||
|
@ -76,10 +74,6 @@ MTC_TransportMaster::~MTC_TransportMaster()
|
|||
{
|
||||
port_connections.drop_connections();
|
||||
session_connections.drop_connections();
|
||||
|
||||
if (_session && did_reset_tc_format) {
|
||||
_session->config.set_timecode_format (saved_tc_format);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -135,7 +129,6 @@ MTC_TransportMaster::set_session (Session *s)
|
|||
last_mtc_fps_byte = _session->get_mtc_timecode_bits ();
|
||||
quarter_frame_duration = (double) (_session->samples_per_timecode_frame() / 4.0);
|
||||
mtc_timecode = _session->config.get_timecode_format();
|
||||
a3e_timecode = _session->config.get_timecode_format();
|
||||
|
||||
parse_timecode_offset ();
|
||||
reset (true);
|
||||
|
@ -265,6 +258,7 @@ MTC_TransportMaster::reset (bool with_position)
|
|||
window_end = 0;
|
||||
transport_direction = 1;
|
||||
_current_delta = 0;
|
||||
timecode_format_valid = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -342,7 +336,7 @@ MTC_TransportMaster::update_mtc_time (const MIDI::byte *msg, bool was_full, samp
|
|||
*/
|
||||
DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::update_mtc_time - TID:%1\n", pthread_name()));
|
||||
TimecodeFormat tc_format;
|
||||
bool reset_tc = true;
|
||||
bool have_tc = true;
|
||||
|
||||
timecode.hours = msg[3];
|
||||
timecode.minutes = msg[2];
|
||||
|
@ -397,46 +391,12 @@ MTC_TransportMaster::update_mtc_time (const MIDI::byte *msg, bool was_full, samp
|
|||
}
|
||||
timecode.rate = _session->timecode_frames_per_second();
|
||||
timecode.drop = _session->timecode_drop_frames();
|
||||
reset_tc = false;
|
||||
have_tc = false;
|
||||
}
|
||||
|
||||
if (reset_tc) {
|
||||
TimecodeFormat cur_timecode = _session->config.get_timecode_format();
|
||||
if (Config->get_timecode_sync_frame_rate()) {
|
||||
/* enforce time-code */
|
||||
if (!did_reset_tc_format) {
|
||||
saved_tc_format = cur_timecode;
|
||||
did_reset_tc_format = true;
|
||||
}
|
||||
if (cur_timecode != tc_format) {
|
||||
if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) {
|
||||
warning << string_compose(_("Session framerate adjusted from %1 TO: MTC's %2."),
|
||||
Timecode::timecode_format_name(cur_timecode),
|
||||
Timecode::timecode_format_name(tc_format))
|
||||
<< endmsg;
|
||||
}
|
||||
}
|
||||
_session->config.set_timecode_format (tc_format);
|
||||
} else {
|
||||
/* only warn about TC mismatch */
|
||||
if (mtc_timecode != tc_format) printed_timecode_warning = false;
|
||||
if (a3e_timecode != cur_timecode) printed_timecode_warning = false;
|
||||
|
||||
if (cur_timecode != tc_format && ! printed_timecode_warning) {
|
||||
if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) {
|
||||
warning << string_compose(_("Session and MTC framerate mismatch: MTC:%1 %2:%3."),
|
||||
Timecode::timecode_format_name(tc_format),
|
||||
PROGRAM_NAME,
|
||||
Timecode::timecode_format_name(cur_timecode))
|
||||
<< endmsg;
|
||||
}
|
||||
printed_timecode_warning = true;
|
||||
}
|
||||
}
|
||||
if (have_tc) {
|
||||
mtc_timecode = tc_format;
|
||||
a3e_timecode = cur_timecode;
|
||||
|
||||
speedup_due_to_tc_mismatch = timecode.rate / Timecode::timecode_to_frames_per_second(a3e_timecode);
|
||||
timecode_format_valid = true; /* SET FLAG */
|
||||
}
|
||||
|
||||
/* do a careful conversion of the timecode value to a position
|
||||
|
@ -452,8 +412,7 @@ MTC_TransportMaster::update_mtc_time (const MIDI::byte *msg, bool was_full, samp
|
|||
timecode_negative_offset, timecode_offset
|
||||
);
|
||||
|
||||
DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC at %1 TC %2 = mtc_frame %3 (from full message ? %4) tc-ratio %5\n",
|
||||
now, timecode, mtc_frame, was_full, speedup_due_to_tc_mismatch));
|
||||
DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC at %1 TC %2 = mtc_frame %3 (from full message ? %4)\n", now, timecode, mtc_frame, was_full));
|
||||
|
||||
if (was_full || outside_window (mtc_frame)) {
|
||||
DEBUG_TRACE (DEBUG::MTC, string_compose ("update_mtc_time: full TC %1 or outside window %2 MTC %3\n", was_full, outside_window (mtc_frame), mtc_frame));
|
||||
|
|
|
@ -511,6 +511,9 @@ TransportMaster::set_request_mask (TransportRequestType t)
|
|||
|
||||
TimecodeTransportMaster::TimecodeTransportMaster (std::string const & name, SyncSource type)
|
||||
: TransportMaster (type, name)
|
||||
, timecode_offset (0)
|
||||
, timecode_negative_offset (false)
|
||||
, timecode_format_valid (false)
|
||||
, _fr2997 (Properties::fr2997, false)
|
||||
{
|
||||
register_properties ();
|
||||
|
|
|
@ -102,6 +102,8 @@ TransportMasterManager::set_session (Session* s)
|
|||
|
||||
Glib::Threads::RWLock::ReaderLock lm (lock);
|
||||
|
||||
maybe_restore_tc_format ();
|
||||
|
||||
config_connection.disconnect ();
|
||||
|
||||
_session = s;
|
||||
|
@ -177,6 +179,7 @@ TransportMasterManager::pre_process_transport_masters (pframes_t nframes, sample
|
|||
}
|
||||
|
||||
if (!_session->config.get_external_sync()) {
|
||||
maybe_restore_tc_format ();
|
||||
DEBUG_TRACE (DEBUG::Slave, string_compose ("no external sync, use session actual speed of %1\n", _session->actual_speed() ? _session->actual_speed() : 1.0));
|
||||
return _session->actual_speed () ? _session->actual_speed() : 1.0;
|
||||
}
|
||||
|
@ -231,7 +234,7 @@ TransportMasterManager::pre_process_transport_masters (pframes_t nframes, sample
|
|||
if (master_dll_initstate == 0) {
|
||||
|
||||
init_transport_master_dll (_master_speed, _master_position);
|
||||
DEBUG_TRACE (DEBUG::Slave, string_compose ("no roll3 - still initializing master DLL, will be %1 next process cycle\n", master_dll_initstate));
|
||||
DEBUG_TRACE (DEBUG::Slave, string_compose ("initializing master DLL, will be %1 next process cycle\n", master_dll_initstate));
|
||||
|
||||
return _master_speed;
|
||||
}
|
||||
|
@ -298,11 +301,56 @@ TransportMasterManager::pre_process_transport_masters (pframes_t nframes, sample
|
|||
|
||||
_master_invalid_this_cycle = false;
|
||||
|
||||
maybe_set_tc_format ();
|
||||
|
||||
DEBUG_TRACE (DEBUG::Slave, string_compose ("computed resampling ratio as %1 with position = %2 and speed = %3\n", engine_speed, _master_position, _master_speed));
|
||||
|
||||
return engine_speed;
|
||||
}
|
||||
|
||||
void
|
||||
TransportMasterManager::maybe_restore_tc_format ()
|
||||
{
|
||||
if (_session && _session_tc_format) {
|
||||
_session->config.set_timecode_format (*_session_tc_format);
|
||||
}
|
||||
_session_tc_format.reset ();
|
||||
}
|
||||
|
||||
void
|
||||
TransportMasterManager::maybe_set_tc_format ()
|
||||
{
|
||||
if (!Config->get_timecode_sync_frame_rate() || !_session) {
|
||||
return;
|
||||
}
|
||||
boost::shared_ptr<TimecodeTransportMaster> tcm;
|
||||
if ((tcm = boost::dynamic_pointer_cast<TimecodeTransportMaster>(_current_master)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tcm->apparent_timecode_format_valid ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Timecode::TimecodeFormat stf = _session->config.get_timecode_format();
|
||||
Timecode::TimecodeFormat mtf = tcm->apparent_timecode_format ();
|
||||
|
||||
if (stf == mtf) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* save session's original TC */
|
||||
if (!_session_tc_format) {
|
||||
_session_tc_format = stf;
|
||||
}
|
||||
|
||||
warning << string_compose(_("Transport master adjusted framerate from %1 to %2."),
|
||||
Timecode::timecode_format_name(stf),
|
||||
Timecode::timecode_format_name(mtf))
|
||||
<< endmsg;
|
||||
|
||||
_session->config.set_timecode_format (mtf);
|
||||
}
|
||||
|
||||
void
|
||||
TransportMasterManager::init_transport_master_dll (double speed, samplepos_t pos)
|
||||
|
@ -423,6 +471,8 @@ TransportMasterManager::set_current_locked (boost::shared_ptr<TransportMaster> c
|
|||
}
|
||||
}
|
||||
|
||||
maybe_restore_tc_format ();
|
||||
|
||||
if (!c->usable()) {
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user