mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-08 07:45:00 +01:00
implement TC offset for slave&generator.
Many related changes that require atomic update, mostly
because ClockOption slots changed:
* change offset config format to std:string (backwards compat - reads 0)
* make Timecode offset independent from fps
* sample_to_timecode() handle negative sample-num
* audio-clock fix entry and edit of negative numbers
* option editor:
- remove old global internal offset
- add slave & generator TC entry
- still needs UI cleanup, tooltops, maybe sep. tab..
* LTC & MTC slave& generator:
- cache offset
- subscribe to parameter changes
git-svn-id: svn://localhost/ardour2/branches/3.0@13485 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
f761de0d70
commit
e1581242ca
13 changed files with 164 additions and 37 deletions
|
|
@ -915,7 +915,7 @@ AudioClock::end_edit_relative (bool add)
|
||||||
} else {
|
} else {
|
||||||
framepos_t c = current_time();
|
framepos_t c = current_time();
|
||||||
|
|
||||||
if (c > frames) {
|
if (c > frames || _negative_allowed) {
|
||||||
set (c - frames, true);
|
set (c - frames, true);
|
||||||
} else {
|
} else {
|
||||||
set (0, true);
|
set (0, true);
|
||||||
|
|
@ -932,6 +932,11 @@ AudioClock::end_edit_relative (bool add)
|
||||||
void
|
void
|
||||||
AudioClock::session_configuration_changed (std::string p)
|
AudioClock::session_configuration_changed (std::string p)
|
||||||
{
|
{
|
||||||
|
if (_negative_allowed) {
|
||||||
|
/* session option editor clock */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (p == "sync-source" || p == "external-sync") {
|
if (p == "sync-source" || p == "external-sync") {
|
||||||
set (current_time(), true);
|
set (current_time(), true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1897,10 +1902,23 @@ bool
|
||||||
AudioClock::timecode_validate_edit (const string&)
|
AudioClock::timecode_validate_edit (const string&)
|
||||||
{
|
{
|
||||||
Timecode::Time TC;
|
Timecode::Time TC;
|
||||||
|
int hours;
|
||||||
char ignored[2];
|
char ignored[2];
|
||||||
|
|
||||||
if (sscanf (_layout->get_text().c_str(), "%" PRId32 ":%" PRId32 ":%" PRId32 "%[:;]%" PRId32,
|
if (sscanf (_layout->get_text().c_str(), "%" PRId32 ":%" PRId32 ":%" PRId32 "%[:;]%" PRId32,
|
||||||
&TC.hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 5) {
|
&hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hours < 0) {
|
||||||
|
TC.hours = hours * -1;
|
||||||
|
TC.negative = true;
|
||||||
|
} else {
|
||||||
|
TC.hours = hours;
|
||||||
|
TC.negative = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TC.negative && !_negative_allowed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1947,19 +1965,22 @@ AudioClock::frames_from_timecode_string (const string& str) const
|
||||||
Timecode::Time TC;
|
Timecode::Time TC;
|
||||||
framepos_t sample;
|
framepos_t sample;
|
||||||
char ignored[2];
|
char ignored[2];
|
||||||
|
int hours;
|
||||||
|
|
||||||
if (sscanf (str.c_str(), "%d:%d:%d%[:;]%d", &TC.hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 5) {
|
if (sscanf (str.c_str(), "%d:%d:%d%[:;]%d", &hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 5) {
|
||||||
error << string_compose (_("programming error: %1 %2"), "badly formatted timecode clock string", str) << endmsg;
|
error << string_compose (_("programming error: %1 %2"), "badly formatted timecode clock string", str) << endmsg;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
TC.hours = abs(hours);
|
||||||
TC.negative = edit_is_negative;
|
|
||||||
TC.rate = _session->timecode_frames_per_second();
|
TC.rate = _session->timecode_frames_per_second();
|
||||||
TC.drop= _session->timecode_drop_frames();
|
TC.drop= _session->timecode_drop_frames();
|
||||||
|
|
||||||
_session->timecode_to_sample (TC, sample, false /* use_offset */, false /* use_subframes */ );
|
_session->timecode_to_sample (TC, sample, false /* use_offset */, false /* use_subframes */ );
|
||||||
|
|
||||||
// timecode_tester ();
|
// timecode_tester ();
|
||||||
|
if (edit_is_negative) {
|
||||||
|
sample = - sample;
|
||||||
|
}
|
||||||
|
|
||||||
return sample;
|
return sample;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "ardour/rc_configuration.h"
|
#include "ardour/rc_configuration.h"
|
||||||
#include "ardour/utils.h"
|
#include "ardour/utils.h"
|
||||||
#include "ardour/dB.h"
|
#include "ardour/dB.h"
|
||||||
|
#include "ardour/session.h"
|
||||||
|
|
||||||
#include "option_editor.h"
|
#include "option_editor.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
|
|
@ -284,7 +285,7 @@ FaderOption::add_to_page (OptionEditorPage* p)
|
||||||
add_widgets_to_page (p, &_label, &_box);
|
add_widgets_to_page (p, &_label, &_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClockOption::ClockOption (string const & i, string const & n, sigc::slot<framecnt_t> g, sigc::slot<bool, framecnt_t> s)
|
ClockOption::ClockOption (string const & i, string const & n, sigc::slot<std::string> g, sigc::slot<bool, std::string> s)
|
||||||
: Option (i, n)
|
: Option (i, n)
|
||||||
, _clock (X_("timecode-offset"), false, X_(""), true, false, true, false)
|
, _clock (X_("timecode-offset"), false, X_(""), true, false, true, false)
|
||||||
, _get (g)
|
, _get (g)
|
||||||
|
|
@ -299,13 +300,24 @@ ClockOption::ClockOption (string const & i, string const & n, sigc::slot<framecn
|
||||||
void
|
void
|
||||||
ClockOption::set_state_from_config ()
|
ClockOption::set_state_from_config ()
|
||||||
{
|
{
|
||||||
_clock.set (_get (), true);
|
Timecode::Time TC;
|
||||||
|
framepos_t when;
|
||||||
|
if (!Timecode::parse_timecode_format(_get(), TC)) {
|
||||||
|
_clock.set (0, true);
|
||||||
|
}
|
||||||
|
TC.rate = _session->frames_per_timecode_frame();
|
||||||
|
TC.drop = _session->timecode_drop_frames();
|
||||||
|
_session->timecode_to_sample(TC, when, false, false);
|
||||||
|
if (TC.negative) { when=-when; }
|
||||||
|
_clock.set (when, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClockOption::save_clock_time ()
|
ClockOption::save_clock_time ()
|
||||||
{
|
{
|
||||||
_set (_clock.current_time());
|
Timecode::Time TC;
|
||||||
|
_session->sample_to_timecode(_clock.current_time(), TC, false, false);
|
||||||
|
_set (Timecode::timecode_format_time(TC));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -317,6 +329,7 @@ ClockOption::add_to_page (OptionEditorPage* p)
|
||||||
void
|
void
|
||||||
ClockOption::set_session (Session* s)
|
ClockOption::set_session (Session* s)
|
||||||
{
|
{
|
||||||
|
_session = s;
|
||||||
_clock.set_session (s);
|
_clock.set_session (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -535,7 +535,7 @@ private:
|
||||||
class ClockOption : public Option
|
class ClockOption : public Option
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClockOption (std::string const &, std::string const &, sigc::slot<ARDOUR::framecnt_t>, sigc::slot<bool, ARDOUR::framecnt_t>);
|
ClockOption (std::string const &, std::string const &, sigc::slot<std::string>, sigc::slot<bool, std::string>);
|
||||||
void set_state_from_config ();
|
void set_state_from_config ();
|
||||||
void add_to_page (OptionEditorPage *);
|
void add_to_page (OptionEditorPage *);
|
||||||
void set_session (ARDOUR::Session *);
|
void set_session (ARDOUR::Session *);
|
||||||
|
|
@ -547,8 +547,9 @@ private:
|
||||||
void save_clock_time ();
|
void save_clock_time ();
|
||||||
Gtk::Label _label;
|
Gtk::Label _label;
|
||||||
AudioClock _clock;
|
AudioClock _clock;
|
||||||
sigc::slot<ARDOUR::framecnt_t> _get;
|
sigc::slot<std::string> _get;
|
||||||
sigc::slot<bool, ARDOUR::framecnt_t> _set;
|
sigc::slot<bool, std::string> _set;
|
||||||
|
ARDOUR::Session *_session;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DirectoryOption : public Option
|
class DirectoryOption : public Option
|
||||||
|
|
|
||||||
|
|
@ -91,24 +91,32 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
|
||||||
|
|
||||||
add_option (_("Timecode"), _vpu);
|
add_option (_("Timecode"), _vpu);
|
||||||
|
|
||||||
ClockOption* co = new ClockOption (
|
|
||||||
"timecode-offset",
|
add_option (_("Timecode"), new OptionEditorHeading (_("Ext Timecode Offsets")));
|
||||||
_("Timecode offset"),
|
|
||||||
sigc::mem_fun (*_session_config, &SessionConfiguration::get_timecode_offset),
|
ClockOption* sco = new ClockOption (
|
||||||
sigc::mem_fun (*_session_config, &SessionConfiguration::set_timecode_offset)
|
"slave-timecode-offset",
|
||||||
|
_("Slave Timecode offset"),
|
||||||
|
sigc::mem_fun (*_session_config, &SessionConfiguration::get_slave_timecode_offset),
|
||||||
|
sigc::mem_fun (*_session_config, &SessionConfiguration::set_slave_timecode_offset)
|
||||||
);
|
);
|
||||||
|
|
||||||
co->set_session (_session);
|
sco->set_session (_session);
|
||||||
co->clock().set_negative_allowed (true);
|
sco->clock().set_negative_allowed (true);
|
||||||
|
|
||||||
add_option (_("Timecode"), co);
|
add_option (_("Timecode"), sco);
|
||||||
|
|
||||||
add_option (_("Timecode"), new BoolOption (
|
ClockOption* gco = new ClockOption (
|
||||||
"timecode-offset-negative",
|
"timecode-generator-offset",
|
||||||
_("Timecode Offset Negative"),
|
_("Timecode Generator offset"),
|
||||||
sigc::mem_fun (*_session_config, &SessionConfiguration::get_timecode_offset_negative),
|
sigc::mem_fun (*_session_config, &SessionConfiguration::get_timecode_generator_offset),
|
||||||
sigc::mem_fun (*_session_config, &SessionConfiguration::set_timecode_offset_negative)
|
sigc::mem_fun (*_session_config, &SessionConfiguration::set_timecode_generator_offset)
|
||||||
));
|
);
|
||||||
|
|
||||||
|
gco->set_session (_session);
|
||||||
|
gco->clock().set_negative_allowed (true);
|
||||||
|
|
||||||
|
add_option (_("Timecode"), gco);
|
||||||
|
|
||||||
add_option (_("Timecode"), new OptionEditorHeading (_("JACK Transport/Time Settings")));
|
add_option (_("Timecode"), new OptionEditorHeading (_("JACK Transport/Time Settings")));
|
||||||
|
|
||||||
|
|
@ -300,7 +308,11 @@ SessionOptionEditor::parameter_changed (std::string const & p)
|
||||||
_vpu->set_sensitive(true);
|
_vpu->set_sensitive(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (p == "timecode-format") {
|
||||||
|
/* update offset clocks */
|
||||||
|
parameter_changed("timecode-generator-offset");
|
||||||
|
parameter_changed("slave-timecode-offset");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the presence of absence of a monitor section is not really a regular session
|
/* the presence of absence of a monitor section is not really a regular session
|
||||||
|
|
|
||||||
|
|
@ -1203,6 +1203,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
framepos_t ltc_enc_off;
|
framepos_t ltc_enc_off;
|
||||||
bool restarting;
|
bool restarting;
|
||||||
|
|
||||||
|
framepos_t ltc_timecode_offset;
|
||||||
|
bool ltc_timecode_negative_offset;
|
||||||
|
|
||||||
jack_latency_range_t ltc_out_latency;
|
jack_latency_range_t ltc_out_latency;
|
||||||
|
|
||||||
void ltc_tx_initialize();
|
void ltc_tx_initialize();
|
||||||
|
|
@ -1210,6 +1213,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
void ltc_tx_reset();
|
void ltc_tx_reset();
|
||||||
void ltc_tx_resync_latency();
|
void ltc_tx_resync_latency();
|
||||||
void ltc_tx_recalculate_position();
|
void ltc_tx_recalculate_position();
|
||||||
|
void ltc_tx_parse_offset();
|
||||||
void ltc_tx_send_time_code_for_cycle (framepos_t, framepos_t, double, double, pframes_t nframes);
|
void ltc_tx_send_time_code_for_cycle (framepos_t, framepos_t, double, double, pframes_t nframes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,8 @@ CONFIG_VARIABLE (bool, external_sync, "external-sync", false)
|
||||||
CONFIG_VARIABLE (InsertMergePolicy, insert_merge_policy, "insert-merge-policy", InsertMergeRelax)
|
CONFIG_VARIABLE (InsertMergePolicy, insert_merge_policy, "insert-merge-policy", InsertMergeRelax)
|
||||||
CONFIG_VARIABLE (framecnt_t, timecode_offset, "timecode-offset", 0)
|
CONFIG_VARIABLE (framecnt_t, timecode_offset, "timecode-offset", 0)
|
||||||
CONFIG_VARIABLE (bool, timecode_offset_negative, "timecode-offset-negative", true)
|
CONFIG_VARIABLE (bool, timecode_offset_negative, "timecode-offset-negative", true)
|
||||||
CONFIG_VARIABLE (framecnt_t, slave_timecode_offset, "slave-timecode-offset", 0)
|
CONFIG_VARIABLE (std::string, slave_timecode_offset, "slave-timecode-offset", " 00:00:00:00")
|
||||||
CONFIG_VARIABLE (bool, slave_timecode_offset_negative, "slave-timecode-offset-negative", true)
|
CONFIG_VARIABLE (std::string, timecode_generator_offset, "timecode-generator-offset", " 00:00:00:00")
|
||||||
CONFIG_VARIABLE (framecnt_t, timecode_generator_offset, "timecode-generator-offset", 0)
|
|
||||||
CONFIG_VARIABLE (bool, timecode_generator_offset_negative, "timecode-generator-offset-negative", true)
|
|
||||||
CONFIG_VARIABLE (bool, glue_new_markers_to_bars_and_beats, "glue-new-markers-to-bars-and-beats", false)
|
CONFIG_VARIABLE (bool, glue_new_markers_to_bars_and_beats, "glue-new-markers-to-bars-and-beats", false)
|
||||||
CONFIG_VARIABLE (bool, midi_copy_is_fork, "midi-copy-is-fork", false)
|
CONFIG_VARIABLE (bool, midi_copy_is_fork, "midi-copy-is-fork", false)
|
||||||
CONFIG_VARIABLE (bool, glue_new_regions_to_bars_and_beats, "glue-new-regions-to-bars-and-beats", false)
|
CONFIG_VARIABLE (bool, glue_new_regions_to_bars_and_beats, "glue-new-regions-to-bars-and-beats", false)
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,9 @@ class TimecodeSlave : public Slave {
|
||||||
of the TC source position.
|
of the TC source position.
|
||||||
*/
|
*/
|
||||||
virtual std::string approximate_current_position() const = 0;
|
virtual std::string approximate_current_position() const = 0;
|
||||||
|
|
||||||
|
framepos_t timecode_offset;
|
||||||
|
bool timecode_negative_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MTC_Slave : public TimecodeSlave {
|
class MTC_Slave : public TimecodeSlave {
|
||||||
|
|
@ -274,6 +277,7 @@ class MTC_Slave : public TimecodeSlave {
|
||||||
Session& session;
|
Session& session;
|
||||||
MIDI::Port* port;
|
MIDI::Port* port;
|
||||||
PBD::ScopedConnectionList port_connections;
|
PBD::ScopedConnectionList port_connections;
|
||||||
|
PBD::ScopedConnection config_connection;
|
||||||
bool can_notify_on_unknown_rate;
|
bool can_notify_on_unknown_rate;
|
||||||
|
|
||||||
static const int frame_tolerance;
|
static const int frame_tolerance;
|
||||||
|
|
@ -327,6 +331,8 @@ class MTC_Slave : public TimecodeSlave {
|
||||||
bool outside_window (framepos_t) const;
|
bool outside_window (framepos_t) const;
|
||||||
void init_mtc_dll(framepos_t, double);
|
void init_mtc_dll(framepos_t, double);
|
||||||
void init_engine_dll (framepos_t, framepos_t);
|
void init_engine_dll (framepos_t, framepos_t);
|
||||||
|
void parse_timecode_offset();
|
||||||
|
void parameter_changed(std::string const & p);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef HAVE_LTC
|
#ifdef HAVE_LTC
|
||||||
|
|
@ -359,6 +365,8 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
void resync_xrun();
|
void resync_xrun();
|
||||||
void resync_latency();
|
void resync_latency();
|
||||||
|
void parse_timecode_offset();
|
||||||
|
void parameter_changed(std::string const & p);
|
||||||
|
|
||||||
Session& session;
|
Session& session;
|
||||||
bool did_reset_tc_format;
|
bool did_reset_tc_format;
|
||||||
|
|
@ -384,6 +392,7 @@ public:
|
||||||
Timecode::TimecodeFormat a3e_timecode;
|
Timecode::TimecodeFormat a3e_timecode;
|
||||||
|
|
||||||
PBD::ScopedConnectionList port_connections;
|
PBD::ScopedConnectionList port_connections;
|
||||||
|
PBD::ScopedConnection config_connection;
|
||||||
jack_latency_range_t ltc_slave_latency;
|
jack_latency_range_t ltc_slave_latency;
|
||||||
|
|
||||||
/* DLL - chase LTC */
|
/* DLL - chase LTC */
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@ LTC_Slave::LTC_Slave (Session& s)
|
||||||
memset(&prev_frame, 0, sizeof(LTCFrameExt));
|
memset(&prev_frame, 0, sizeof(LTCFrameExt));
|
||||||
|
|
||||||
decoder = ltc_decoder_create((int) frames_per_ltc_frame, 128 /*queue size*/);
|
decoder = ltc_decoder_create((int) frames_per_ltc_frame, 128 /*queue size*/);
|
||||||
|
|
||||||
|
session.config.ParameterChanged.connect_same_thread (config_connection, boost::bind (<C_Slave::parameter_changed, this, _1));
|
||||||
|
parse_timecode_offset();
|
||||||
reset();
|
reset();
|
||||||
resync_latency();
|
resync_latency();
|
||||||
session.Xrun.connect_same_thread (port_connections, boost::bind (<C_Slave::resync_xrun, this));
|
session.Xrun.connect_same_thread (port_connections, boost::bind (<C_Slave::resync_xrun, this));
|
||||||
|
|
@ -69,6 +72,7 @@ LTC_Slave::LTC_Slave (Session& s)
|
||||||
LTC_Slave::~LTC_Slave()
|
LTC_Slave::~LTC_Slave()
|
||||||
{
|
{
|
||||||
port_connections.drop_connections();
|
port_connections.drop_connections();
|
||||||
|
config_connection.disconnect();
|
||||||
|
|
||||||
if (did_reset_tc_format) {
|
if (did_reset_tc_format) {
|
||||||
session.config.set_timecode_format (saved_tc_format);
|
session.config.set_timecode_format (saved_tc_format);
|
||||||
|
|
@ -77,6 +81,27 @@ LTC_Slave::~LTC_Slave()
|
||||||
ltc_decoder_free(decoder);
|
ltc_decoder_free(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LTC_Slave::parse_timecode_offset() {
|
||||||
|
Timecode::Time offset_tc;
|
||||||
|
Timecode::parse_timecode_format(session.config.get_slave_timecode_offset(), offset_tc);
|
||||||
|
offset_tc.rate = session.timecode_frames_per_second();
|
||||||
|
offset_tc.drop = session.timecode_drop_frames();
|
||||||
|
session.timecode_to_sample(offset_tc, timecode_offset, false, false);
|
||||||
|
timecode_negative_offset = offset_tc.negative;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LTC_Slave::parameter_changed (std::string const & p)
|
||||||
|
{
|
||||||
|
if (p == "slave-timecode-offset"
|
||||||
|
|| p == "subframes-per-frame"
|
||||||
|
|| p == "timecode-format"
|
||||||
|
) {
|
||||||
|
parse_timecode_offset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ARDOUR::framecnt_t
|
ARDOUR::framecnt_t
|
||||||
LTC_Slave::resolution () const
|
LTC_Slave::resolution () const
|
||||||
{
|
{
|
||||||
|
|
@ -334,7 +359,7 @@ LTC_Slave::process_ltc(framepos_t const now)
|
||||||
Timecode::timecode_to_sample (timecode, ltc_frame, true, false,
|
Timecode::timecode_to_sample (timecode, ltc_frame, true, false,
|
||||||
double(session.frame_rate()),
|
double(session.frame_rate()),
|
||||||
session.config.get_subframes_per_frame(),
|
session.config.get_subframes_per_frame(),
|
||||||
session.config.get_slave_timecode_offset_negative(), session.config.get_slave_timecode_offset()
|
timecode_negative_offset, timecode_offset
|
||||||
);
|
);
|
||||||
|
|
||||||
framepos_t cur_timestamp = frame.off_end + 1;
|
framepos_t cur_timestamp = frame.off_end + 1;
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
|
||||||
a3e_timecode = session.config.get_timecode_format();
|
a3e_timecode = session.config.get_timecode_format();
|
||||||
printed_timecode_warning = false;
|
printed_timecode_warning = false;
|
||||||
|
|
||||||
|
session.config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&MTC_Slave::parameter_changed, this, _1));
|
||||||
|
parse_timecode_offset();
|
||||||
reset (true);
|
reset (true);
|
||||||
rebind (p);
|
rebind (p);
|
||||||
}
|
}
|
||||||
|
|
@ -73,6 +75,7 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
|
||||||
MTC_Slave::~MTC_Slave()
|
MTC_Slave::~MTC_Slave()
|
||||||
{
|
{
|
||||||
port_connections.drop_connections();
|
port_connections.drop_connections();
|
||||||
|
config_connection.disconnect();
|
||||||
|
|
||||||
while (busy_guard1 != busy_guard2) {
|
while (busy_guard1 != busy_guard2) {
|
||||||
/* make sure MIDI parser is not currently calling any callbacks in here,
|
/* make sure MIDI parser is not currently calling any callbacks in here,
|
||||||
|
|
@ -101,6 +104,27 @@ MTC_Slave::rebind (MIDI::Port& p)
|
||||||
port->parser()->mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
|
port->parser()->mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MTC_Slave::parse_timecode_offset() {
|
||||||
|
Timecode::Time offset_tc;
|
||||||
|
Timecode::parse_timecode_format(session.config.get_slave_timecode_offset(), offset_tc);
|
||||||
|
offset_tc.rate = session.timecode_frames_per_second();
|
||||||
|
offset_tc.drop = session.timecode_drop_frames();
|
||||||
|
session.timecode_to_sample(offset_tc, timecode_offset, false, false);
|
||||||
|
timecode_negative_offset = offset_tc.negative;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MTC_Slave::parameter_changed (std::string const & p)
|
||||||
|
{
|
||||||
|
if (p == "slave-timecode-offset"
|
||||||
|
|| p == "subframes-per-frame"
|
||||||
|
|| p == "timecode-format"
|
||||||
|
) {
|
||||||
|
parse_timecode_offset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MTC_Slave::give_slave_full_control_over_transport_speed() const
|
MTC_Slave::give_slave_full_control_over_transport_speed() const
|
||||||
{
|
{
|
||||||
|
|
@ -390,7 +414,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now)
|
||||||
Timecode::timecode_to_sample (timecode, mtc_frame, true, false,
|
Timecode::timecode_to_sample (timecode, mtc_frame, true, false,
|
||||||
double(session.frame_rate()),
|
double(session.frame_rate()),
|
||||||
session.config.get_subframes_per_frame(),
|
session.config.get_subframes_per_frame(),
|
||||||
session.config.get_slave_timecode_offset_negative(), session.config.get_slave_timecode_offset()
|
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",
|
DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC at %1 TC %2 = mtc_frame %3 (from full message ? %4) tc-ratio %5\n",
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ Session::ltc_tx_initialize()
|
||||||
{
|
{
|
||||||
ltc_enc_tcformat = config.get_timecode_format();
|
ltc_enc_tcformat = config.get_timecode_format();
|
||||||
|
|
||||||
|
ltc_tx_parse_offset();
|
||||||
DEBUG_TRACE (DEBUG::LTC, string_compose("LTC TX init sr: %1 fps: %2\n", nominal_frame_rate(), timecode_to_frames_per_second(ltc_enc_tcformat)));
|
DEBUG_TRACE (DEBUG::LTC, string_compose("LTC TX init sr: %1 fps: %2\n", nominal_frame_rate(), timecode_to_frames_per_second(ltc_enc_tcformat)));
|
||||||
ltc_encoder = ltc_encoder_create(nominal_frame_rate(),
|
ltc_encoder = ltc_encoder_create(nominal_frame_rate(),
|
||||||
timecode_to_frames_per_second(ltc_enc_tcformat),
|
timecode_to_frames_per_second(ltc_enc_tcformat),
|
||||||
|
|
@ -118,6 +119,16 @@ Session::ltc_tx_reset()
|
||||||
ltc_encoder_reset(ltc_encoder);
|
ltc_encoder_reset(ltc_encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Session::ltc_tx_parse_offset() {
|
||||||
|
Timecode::Time offset_tc;
|
||||||
|
Timecode::parse_timecode_format(config.get_timecode_generator_offset(), offset_tc);
|
||||||
|
offset_tc.rate = timecode_frames_per_second();
|
||||||
|
offset_tc.drop = timecode_drop_frames();
|
||||||
|
timecode_to_sample(offset_tc, ltc_timecode_offset, false, false);
|
||||||
|
ltc_timecode_negative_offset = !offset_tc.negative;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Session::ltc_tx_recalculate_position()
|
Session::ltc_tx_recalculate_position()
|
||||||
{
|
{
|
||||||
|
|
@ -135,7 +146,7 @@ Session::ltc_tx_recalculate_position()
|
||||||
Timecode::timecode_to_sample (a3tc, ltc_enc_pos, true, false,
|
Timecode::timecode_to_sample (a3tc, ltc_enc_pos, true, false,
|
||||||
(double)frame_rate(),
|
(double)frame_rate(),
|
||||||
config.get_subframes_per_frame(),
|
config.get_subframes_per_frame(),
|
||||||
config.get_timecode_generator_offset_negative(), config.get_timecode_generator_offset()
|
ltc_timecode_negative_offset, ltc_timecode_offset
|
||||||
);
|
);
|
||||||
restarting = false;
|
restarting = false;
|
||||||
}
|
}
|
||||||
|
|
@ -204,6 +215,7 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
|
||||||
}
|
}
|
||||||
ltc_encoder_set_filter(ltc_encoder, LTC_RISE_TIME(ltc_speed));
|
ltc_encoder_set_filter(ltc_encoder, LTC_RISE_TIME(ltc_speed));
|
||||||
ltc_enc_tcformat = cur_timecode;
|
ltc_enc_tcformat = cur_timecode;
|
||||||
|
ltc_tx_parse_offset();
|
||||||
ltc_tx_reset();
|
ltc_tx_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,14 +377,14 @@ Session::ltc_tx_send_time_code_for_cycle (framepos_t start_frame, framepos_t end
|
||||||
timecode_drop_frames(),
|
timecode_drop_frames(),
|
||||||
(double)frame_rate(),
|
(double)frame_rate(),
|
||||||
config.get_subframes_per_frame(),
|
config.get_subframes_per_frame(),
|
||||||
config.get_timecode_generator_offset_negative(), config.get_timecode_generator_offset()
|
ltc_timecode_negative_offset, ltc_timecode_offset
|
||||||
);
|
);
|
||||||
|
|
||||||
/* convert timecode back to sample-position */
|
/* convert timecode back to sample-position */
|
||||||
Timecode::timecode_to_sample (tc_start, tc_sample_start, true, false,
|
Timecode::timecode_to_sample (tc_start, tc_sample_start, true, false,
|
||||||
(double)frame_rate(),
|
(double)frame_rate(),
|
||||||
config.get_subframes_per_frame(),
|
config.get_subframes_per_frame(),
|
||||||
config.get_timecode_generator_offset_negative(), config.get_timecode_generator_offset()
|
ltc_timecode_negative_offset, ltc_timecode_offset
|
||||||
);
|
);
|
||||||
|
|
||||||
/* difference between current frame and TC frame in samples */
|
/* difference between current frame and TC frame in samples */
|
||||||
|
|
|
||||||
|
|
@ -3565,6 +3565,10 @@ Session::config_changed (std::string p, bool ours)
|
||||||
reconnect_ltc_input ();
|
reconnect_ltc_input ();
|
||||||
} else if (p == "ltc-sink-port") {
|
} else if (p == "ltc-sink-port") {
|
||||||
reconnect_ltc_output ();
|
reconnect_ltc_output ();
|
||||||
|
#ifdef HAVE_LTC
|
||||||
|
} else if (p == "timecode-generator-offset") {
|
||||||
|
ltc_tx_parse_offset();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
set_dirty ();
|
set_dirty ();
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,9 @@ Session::sync_time_vars ()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
#ifdef HAVE_LTC
|
||||||
|
ltc_tx_parse_offset();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "timecode/time.h"
|
#include "timecode/time.h"
|
||||||
|
|
||||||
|
|
@ -761,8 +762,8 @@ sample_to_timecode (
|
||||||
int64_t offset_sample;
|
int64_t offset_sample;
|
||||||
|
|
||||||
if (!use_offset) {
|
if (!use_offset) {
|
||||||
offset_sample = sample;
|
timecode.negative = (sample < 0);
|
||||||
timecode.negative = false;
|
offset_sample = llabs(sample);
|
||||||
} else {
|
} else {
|
||||||
if (offset_is_negative) {
|
if (offset_is_negative) {
|
||||||
offset_sample = sample + offset_samples;
|
offset_sample = sample + offset_samples;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue