more MTC stuff, including toggleable use of torben's PI controller

git-svn-id: svn://localhost/ardour2/branches/3.0@6265 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-12-02 21:26:26 +00:00
parent c17b4a30a5
commit 9dddffcc8f
12 changed files with 261 additions and 206 deletions

View File

@ -28,7 +28,7 @@ def configure(conf):
def build(bld):
obj = bld.new_task_gen('cxx', 'shlib',
uselib = 'COREAUDIO CORESERVICES COREFOUNDATION AUDIOTOOLBOX AUDIOUNITS OSX GTKOSX')
uselib = 'COREAUDIO CORESERVICES COREFOUNDATION AUDIOTOOLBOX AUDIOUNITS OSX GTKOSX')
obj.source = libappleutility_sources
obj.export_incdirs = ['.']
obj.includes = ['.']
@ -41,4 +41,4 @@ def shutdown():
autowaf.shutdown()
def i18n(bld):
pass
pass

View File

@ -986,6 +986,13 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
PostTransportClearSubstate = 0x80000
};
enum SlaveState {
Stopped,
Waiting,
Running
};
SlaveState slave_state() const { return _slave_state; }
protected:
friend class AudioEngine;
@ -1088,20 +1095,13 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
int average_dir;
bool have_first_delta_accumulator;
enum SlaveState {
Stopped,
Waiting,
Running
};
SlaveState slave_state;
SlaveState _slave_state;
nframes_t slave_wait_end;
void reset_slave_state ();
bool follow_slave (nframes_t);
void calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta);
void track_slave_state(float slave_speed, nframes_t slave_transport_frame,
nframes_t this_delta, bool starting);
void track_slave_state(float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta);
void follow_slave_silently(nframes_t nframes, float slave_speed);
void use_sync_source (SyncSource);

View File

@ -29,6 +29,8 @@
#include "midi++/parser.h"
#include "midi++/types.h"
class PIController;
namespace MIDI {
class Port;
}
@ -140,11 +142,18 @@ class Slave {
virtual nframes_t resolution() const = 0;
/**
* @return - when returning true, ARDOUR will wait for one second before transport
* @return - when returning true, ARDOUR will wait for seekahead_distance() before transport
* starts rolling
*/
virtual bool requires_seekahead () const = 0;
/**
* @return the number of frames that this slave wants to seek ahead. Relevant
* only if @func requires_seekahead() returns true.
*/
virtual nframes64_t seekahead_distance() const { return 0; }
/**
* @return - when returning true, ARDOUR will use transport speed 1.0 no matter what
* the slave returns
@ -222,35 +231,40 @@ class MTC_Slave : public Slave, public sigc::trackable {
nframes_t resolution() const;
bool requires_seekahead () const { return true; }
nframes64_t seekahead_distance() const;
bool give_slave_full_control_over_transport_speed() const;
private:
Session& session;
MIDI::Port* port;
std::vector<sigc::connection> connections;
bool can_notify_on_unknown_rate;
PIController* pic;
SafeTime current;
double instantaneous_speed;
nframes_t mtc_frame; /* current time */
nframes_t last_inbound_frame; /* when we got it; audio clocked */
MIDI::byte last_mtc_fps_byte;
bool qtr_frame_messages_valid_for_time;
nframes64_t window_begin;
nframes64_t window_end;
nframes64_t last_mtc_timestamp;
nframes64_t last_mtc_frame;
bool did_reset_tc_format;
TimecodeFormat saved_tc_format;
static const int32_t accumulator_size = 128;
double accumulator[accumulator_size];
int32_t accumulator_index;
bool have_first_accumulated_speed;
size_t speed_accumulator_size;
double* speed_accumulator;
size_t speed_accumulator_cnt;
bool have_first_speed_accumulator;
double average_speed;
void reset ();
void update_mtc_qtr (MIDI::Parser&, int, nframes_t);
void update_mtc_time (const MIDI::byte *, bool, nframes_t);
void update_mtc_status (MIDI::Parser::MTC_Status);
void update_mtc_status (MIDI::MTC_Status);
void read_current (SafeTime *) const;
double compute_apparent_speed (nframes64_t);
void reset_window (nframes64_t);
bool outside_window (nframes64_t) const;
void process_apparent_speed (double);
};
class MIDIClock_Slave : public Slave, public sigc::trackable {
@ -337,24 +351,6 @@ class MIDIClock_Slave : public Slave, public sigc::trackable {
bool _starting;
};
class ADAT_Slave : public Slave
{
public:
ADAT_Slave () {}
~ADAT_Slave () {}
bool speed_and_position (double& speed, nframes64_t& pos) {
speed = 0;
pos = 0;
return false;
}
bool locked() const { return false; }
bool ok() const { return false; }
nframes_t resolution() const { return 1; }
bool requires_seekahead () const { return true; }
};
class JACK_Slave : public Slave
{
public:

View File

@ -136,9 +136,13 @@ _thread_init_callback (void * /*arg*/)
*/
PBD::notify_gui_about_thread_creation (pthread_self(), X_("Audioengine"), 4096);
#ifdef WITH_JACK_MIDI
MIDI::JACK_MidiPort::set_process_thread (pthread_self());
#endif // WITH_JACK_MIDI
}
static void
ardour_jack_error (const char* msg)
{
error << "JACK: " << msg << endmsg;
}
int
@ -188,6 +192,8 @@ AudioEngine::start ()
jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
}
jack_set_error_function (ardour_jack_error);
if (jack_activate (_priv_jack) == 0) {
_running = true;
_has_run = true;
@ -1121,12 +1127,6 @@ AudioEngine::remove_all_ports ()
ports.flush ();
}
static void
ardour_jack_error (const char* msg)
{
error << "JACK: " << msg << endmsg;
}
int
AudioEngine::connect_to_jack (string client_name)
{
@ -1148,8 +1148,6 @@ AudioEngine::connect_to_jack (string client_name)
jack_client_name = jack_get_client_name (_priv_jack);
}
jack_set_error_function (ardour_jack_error);
return 0;
}

View File

@ -18,6 +18,7 @@
*/
#include "pbd/enumwriter.h"
#include "midi++/types.h"
#include "ardour/audiofilesource.h"
#include "ardour/audioregion.h"
@ -40,6 +41,7 @@
using namespace std;
using namespace PBD;
using namespace ARDOUR;
using namespace MIDI;
void
setup_enum_writer ()
@ -115,7 +117,9 @@ setup_enum_writer ()
WaveformShape _WaveformShape;
QuantizeType _QuantizeType;
Session::PostTransportWork _Session_PostTransportWork;
Session::SlaveState _Session_SlaveState;
MTC_Status _MIDI_MTC_Status;
#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
@ -305,6 +309,16 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Session::Event, AutoLoop);
REGISTER (_Session_Event_Type);
REGISTER_CLASS_ENUM (Session, Stopped);
REGISTER_CLASS_ENUM (Session, Waiting);
REGISTER_CLASS_ENUM (Session, Running);
REGISTER (_Session_SlaveState);
REGISTER_ENUM (MTC_Stopped);
REGISTER_ENUM (MTC_Forward);
REGISTER_ENUM (MTC_Backward);
REGISTER (_MIDI_MTC_Status);
REGISTER_CLASS_ENUM (Session, PostTransportStop);
REGISTER_CLASS_ENUM (Session, PostTransportDisableRecord);
REGISTER_CLASS_ENUM (Session, PostTransportPosition);

View File

@ -22,6 +22,7 @@
#include <sys/types.h>
#include <unistd.h>
#include "pbd/error.h"
#include "pbd/enumwriter.h"
#include "pbd/failed_constructor.h"
#include "pbd/pthread_utils.h"
@ -30,7 +31,7 @@
#include "ardour/slave.h"
#include "ardour/session.h"
#include "ardour/audioengine.h"
#include "ardour/cycles.h"
#include "ardour/pi_controller.h"
#include "i18n.h"
@ -45,8 +46,14 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
{
can_notify_on_unknown_rate = true;
did_reset_tc_format = false;
pic = new PIController (1.0, 8);
last_mtc_fps_byte = session.get_mtc_timecode_bits ();
mtc_frame = 0;
speed_accumulator_size = 16;
speed_accumulator = new double[speed_accumulator_size];
rebind (p);
reset ();
@ -57,6 +64,15 @@ MTC_Slave::~MTC_Slave()
if (did_reset_tc_format) {
session.config.set_timecode_format (saved_tc_format);
}
delete pic;
delete [] speed_accumulator;
}
bool
MTC_Slave::give_slave_full_control_over_transport_speed() const
{
return true; // for PiC control */
// return false; // for Session-level computed varispeed
}
void
@ -68,6 +84,8 @@ MTC_Slave::rebind (MIDI::Port& p)
port = &p;
cerr << "Bind to port MTC messages\n";
connections.push_back (port->input()->mtc_time.connect (mem_fun (*this, &MTC_Slave::update_mtc_time)));
connections.push_back (port->input()->mtc_qtr.connect (mem_fun (*this, &MTC_Slave::update_mtc_qtr)));
connections.push_back (port->input()->mtc_status.connect (mem_fun (*this, &MTC_Slave::update_mtc_status)));
@ -76,34 +94,8 @@ MTC_Slave::rebind (MIDI::Port& p)
void
MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, nframes_t now)
{
DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2, valid-for-time? %3\n", which_qtr, now, qtr_frame_messages_valid_for_time));
if (qtr_frame_messages_valid_for_time) {
if (which_qtr != 7) {
/* leave position and speed updates for the last
qtr frame message of the 8 to be taken
care of in update_mtc_time(), invoked
by the Parser right after this.
*/
nframes_t qtr;
qtr = (long) (session.frames_per_timecode_frame() / 4);
mtc_frame += qtr;
double speed = compute_apparent_speed (now);
current.guard1++;
current.position = mtc_frame;
current.timestamp = now;
current.speed = speed;
current.guard2++;
}
last_inbound_frame = now;
}
DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2\n", which_qtr, now));
last_inbound_frame = now;
}
void
@ -116,7 +108,8 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now)
Timecode::Time timecode;
TimecodeFormat tc_format;
bool reset_tc = true;
nframes64_t window_root = -1;
DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full));
timecode.hours = msg[3];
@ -175,24 +168,28 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now)
DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC time timestamp = %1 TC %2 = frame %3 (from full message ? %4)\n",
now, timecode, mtc_frame, was_full));
if (was_full) {
if (was_full || outside_window (mtc_frame)) {
session.timecode_to_sample (timecode, mtc_frame, true, false);
session.request_locate (mtc_frame, false);
session.request_transport_speed (0);
update_mtc_status (MIDI::Parser::MTC_Stopped);
update_mtc_status (MIDI::MTC_Stopped);
window_root = mtc_frame;
reset ();
} else {
/* we've had the first set of 8 qtr frame messages, determine position
and allow continuing qtr frame messages to provide position
and speed information.
and allow continuing qtr frame messages to provide position
and speed information.
*/
qtr_frame_messages_valid_for_time = true;
/* do a careful conversion of the timecode value to a position
so that we take drop/nondrop and all that nonsense into
consideration.
*/
session.timecode_to_sample (timecode, mtc_frame, true, false);
/* We received the last quarter frame 7 quarter frames (1.75 mtc
@ -203,56 +200,84 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now)
mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency();
if (now) {
double speed = compute_apparent_speed (now);
if (last_mtc_timestamp == 0) {
last_mtc_timestamp = now;
last_mtc_frame = mtc_frame;
} else {
if (give_slave_full_control_over_transport_speed()) {
/* PIC
*
* its not the average, but we will assign it to current.speed below
*/
average_speed = pic->get_ratio (session.audible_frame() - mtc_frame);
} else {
/* Non-PiC
*/
nframes64_t time_delta = (now - last_mtc_timestamp);
if (time_delta != 0) {
double apparent_speed = (mtc_frame - last_mtc_frame) / (double) (time_delta);
process_apparent_speed (apparent_speed);
DEBUG_TRACE (DEBUG::Slave, string_compose ("apparent speed was %1 average is now %2\n", apparent_speed, average_speed));
} else {
DEBUG_TRACE (DEBUG::Slave, string_compose ("no apparent calc, average is %1\n", average_speed));
}
/* every second, recalibrate the starting point for the speed measurement */
if (mtc_frame - last_mtc_frame > session.frame_rate()) {
last_mtc_timestamp = now;
last_mtc_frame = mtc_frame;
}
}
}
current.guard1++;
current.position = mtc_frame;
current.timestamp = now;
current.speed = speed;
current.speed = average_speed;
current.guard2++;
window_root = mtc_frame;
}
}
if (now) {
last_inbound_frame = now;
}
if (window_root >= 0) {
reset_window (window_root);
}
}
double
MTC_Slave::compute_apparent_speed (nframes64_t now)
void
MTC_Slave::process_apparent_speed (double this_speed)
{
if (current.timestamp != 0) {
double speed = (double) ((mtc_frame - current.position) / (double) (now - current.timestamp));
DEBUG_TRACE (DEBUG::MTC, string_compose ("instantaneous speed = %1 from %2 / %3\n",
speed, mtc_frame - current.position, now - current.timestamp));
/* crude low pass filter/smoother for speed */
DEBUG_TRACE (DEBUG::MTC, string_compose ("speed cnt %1 sz %2 have %3\n", speed_accumulator_cnt, speed_accumulator_size, have_first_speed_accumulator));
accumulator[accumulator_index++] = speed;
if (accumulator_index >= accumulator_size) {
have_first_accumulated_speed = true;
accumulator_index = 0;
if (speed_accumulator_cnt >= speed_accumulator_size) {
have_first_speed_accumulator = true;
speed_accumulator_cnt = 0;
}
speed_accumulator[speed_accumulator_cnt++] = this_speed;
if (have_first_speed_accumulator) {
average_speed = 0.0;
for (size_t i = 0; i < speed_accumulator_size; ++i) {
average_speed += speed_accumulator[i];
}
if (have_first_accumulated_speed) {
double total = 0;
for (int32_t i = 0; i < accumulator_size; ++i) {
total += accumulator[i];
}
speed = total / accumulator_size;
DEBUG_TRACE (DEBUG::MTC, string_compose ("speed smoothed to %1\n", speed));
}
return speed;
} else {
return 0;
average_speed /= speed_accumulator_size;
}
}
@ -271,16 +296,16 @@ MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
}
void
MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
MTC_Slave::update_mtc_status (MIDI::MTC_Status status)
{
/* XXX !!! thread safety ... called from MIDI I/O context
and process() context (via ::speed_and_position())
*/
DEBUG_TRACE (DEBUG::MTC, string_compose ("new MTC status %1\n", enum_2_string (status)));
switch (status) {
case MTC_Stopped:
mtc_frame = 0;
current.guard1++;
current.position = mtc_frame;
current.timestamp = 0;
@ -290,27 +315,22 @@ MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
break;
case MTC_Forward:
mtc_frame = 0;
current.guard1++;
current.position = mtc_frame;
current.timestamp = 0;
current.speed = 0;
current.guard2++;
break;
case MTC_Backward:
mtc_frame = 0;
current.guard1++;
current.position = mtc_frame;
current.timestamp = 0;
current.speed = 0;
current.guard2++;
break;
}
}
void
@ -365,7 +385,7 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
pos = last.position;
session.request_locate (pos, false);
session.request_transport_speed (0);
update_mtc_status (MIDI::Parser::MTC_Stopped);
update_mtc_status (MIDI::MTC_Stopped);
reset();
DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 1/4 second - reset\n");
return false;
@ -384,7 +404,7 @@ MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
if (last.timestamp && (now > last.timestamp)) {
elapsed = (nframes_t) floor (last.speed * (now - last.timestamp));
DEBUG_TRACE (DEBUG::MTC, string_compose ("last timecode received @ %1, now = %2, elapsed frames = %3 w/speed= %4\n",
last.timestamp, now, elapsed, speed));
last.timestamp, now, elapsed, last.speed));
} else {
elapsed = 0; /* XXX is this right? */
}
@ -422,7 +442,42 @@ MTC_Slave::reset ()
current.timestamp = 0;
current.speed = 0;
current.guard2++;
accumulator_index = 0;
have_first_accumulated_speed = false;
qtr_frame_messages_valid_for_time = false;
window_begin = 0;
window_end = 0;
last_mtc_frame = 0;
last_mtc_timestamp = 0;
average_speed = 0;
have_first_speed_accumulator = false;
speed_accumulator_cnt = 0;
pic->out_of_bounds();
}
void
MTC_Slave::reset_window (nframes64_t root)
{
window_begin = root;
if (session.slave_state() == Session::Running) {
window_end = root + (session.frames_per_timecode_frame() * 2);
} else {
window_end = root + seekahead_distance ();
}
DEBUG_TRACE (DEBUG::MTC, string_compose ("legal MTC window now %1 .. %2\n", window_begin, window_end));
}
nframes64_t
MTC_Slave::seekahead_distance () const
{
/* 1 second */
return session.frame_rate();
}
bool
MTC_Slave::outside_window (nframes64_t pos) const
{
return ((pos < window_begin) || (pos > window_end));
}

View File

@ -1261,7 +1261,7 @@ Session::midi_thread_work ()
}
if (pfd[p].revents & POLLIN) {
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("MIDI fd # %1 has data ready\n", p));
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("MIDI fd # %1 has data ready @ %2\n", p, now));
fds_ready++;
ports[p]->parse (now);
}

View File

@ -461,7 +461,7 @@ Session::reset_slave_state ()
average_slave_delta = 1800;
delta_accumulator_cnt = 0;
have_first_delta_accumulator = false;
slave_state = Stopped;
_slave_state = Stopped;
}
bool
@ -483,7 +483,6 @@ Session::follow_slave (nframes_t nframes)
nframes64_t slave_transport_frame;
nframes_t this_delta;
int dir;
bool starting;
if (!_slave->ok()) {
stop_transport ();
@ -493,7 +492,7 @@ Session::follow_slave (nframes_t nframes)
_slave->speed_and_position (slave_speed, slave_transport_frame);
DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave @ %2 speed %1\n", slave_speed, slave_transport_frame));
DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
if (!_slave->locked()) {
DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
@ -508,7 +507,7 @@ Session::follow_slave (nframes_t nframes)
dir = -1;
}
if ((starting = _slave->starting())) {
if (_slave->starting()) {
slave_speed = 0.0f;
}
@ -524,21 +523,23 @@ Session::follow_slave (nframes_t nframes)
} else {
/* TC source is able to drift relative to us (slave)
so we need to keep track of the drift and adjust
our speed to remain locked.
/* if we are chasing and the average delta between us and the
master gets too big, we want to switch to silent
motion. so keep track of that here.
*/
calculate_moving_average_of_slave_delta(dir, this_delta);
if (_slave_state == Running) {
calculate_moving_average_of_slave_delta(dir, this_delta);
}
}
track_slave_state (slave_speed, slave_transport_frame, this_delta, starting);
track_slave_state (slave_speed, slave_transport_frame, this_delta);
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 starting %5\n",
slave_state, slave_transport_frame, slave_speed, this_delta, starting));
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
_slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
if (slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
if (_transport_speed != 0.0f) {
@ -548,7 +549,6 @@ Session::follow_slave (nframes_t nframes)
float delta;
#ifdef USE_MOVING_AVERAGE_OF_SLAVE
if (average_slave_delta == 0) {
delta = this_delta;
delta *= dir;
@ -556,52 +556,38 @@ Session::follow_slave (nframes_t nframes)
delta = average_slave_delta;
delta *= average_dir;
}
#else
delta = this_delta;
delta *= dir;
#endif
#ifndef NDEBUG
if (slave_speed != 0.0) {
DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
(int) (dir * this_delta),
slave_speed,
_transport_speed,
_transport_frame,
slave_transport_frame,
_transport_frame,
average_slave_delta));
}
if (slave_speed != 0.0) {
DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
(int) (dir * this_delta),
slave_speed,
_transport_speed,
_transport_frame,
slave_transport_frame,
average_slave_delta));
}
#endif
if (fabs(delta) > 2048) {
nframes64_t jump_to = slave_transport_frame + lrintf (_current_frame_rate/5.0f);
/* too far off, so locate and keep rolling */
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave delta %1 is too big, locate to %2\n",
delta, jump_to));
request_locate (jump_to, true);
return false;
if (_slave->give_slave_full_control_over_transport_speed()) {
set_transport_speed (slave_speed, false, false);
} else {
float adjusted_speed = slave_speed + (delta / float(_current_frame_rate));
if (_slave->give_slave_full_control_over_transport_speed()) {
request_transport_speed (slave_speed);
} else {
request_transport_speed (adjusted_speed);
DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
slave_speed));
}
request_transport_speed (adjusted_speed);
DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
slave_speed));
}
if (abs(average_slave_delta) > (long) _slave->resolution()) {
cerr << "average slave delta greater than slave resolution, going to silent motion\n";
if (abs(average_slave_delta) > _slave->resolution()) {
cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
goto silent_motion;
}
}
}
if (!starting && !non_realtime_work_pending()) {
if (_slave_state == Running && !non_realtime_work_pending()) {
/* speed is set, we're locked, and good to go */
return true;
}
@ -645,24 +631,24 @@ Session::calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta)
}
void
Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta, bool starting)
Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta)
{
if (slave_speed != 0.0f) {
/* slave is running */
switch (slave_state) {
switch (_slave_state) {
case Stopped:
if (_slave->requires_seekahead()) {
slave_wait_end = slave_transport_frame + _current_frame_rate;
slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
/* we can call locate() here because we are in process context */
locate (slave_wait_end, false, false);
slave_state = Waiting;
starting = true;
_slave_state = Waiting;
} else {
slave_state = Running;
_slave_state = Running;
Location* al = _locations.auto_loop_location();
@ -678,13 +664,24 @@ Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame,
break;
case Waiting:
default:
break;
}
if (_slave_state == Waiting) {
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
if (slave_transport_frame >= slave_wait_end) {
DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
slave_state = Running;
_slave_state = Running;
/* now perform a "micro-seek" within the disk buffers to realign ourselves
precisely with the master.
*/
bool ok = true;
nframes_t frame_delta = slave_transport_frame - _transport_frame;
@ -713,13 +710,9 @@ Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame,
average_slave_delta = 0L;
this_delta = 0;
}
break;
default:
break;
}
if (slave_state == Running && _transport_speed == 0.0f) {
if (_slave_state == Running && _transport_speed == 0.0f) {
DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
start_transport ();
}
@ -738,7 +731,7 @@ Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame,
force_locate (slave_transport_frame, false);
}
slave_state = Stopped;
_slave_state = Stopped;
}
}

View File

@ -263,7 +263,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
average_slave_delta = 1800; // !!! why 1800 ????
have_first_delta_accumulator = false;
delta_accumulator_cnt = 0;
slave_state = Stopped;
_slave_state = Stopped;
_engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));

View File

@ -132,6 +132,7 @@ libardour_sources = [
'onset_detector.cc',
'panner.cc',
'pcm_utils.cc',
'pi_controller.cc',
'playlist.cc',
'playlist_factory.cc',
'plugin.cc',

View File

@ -116,12 +116,6 @@ class Parser : public sigc::trackable {
/* MTC */
enum MTC_Status {
MTC_Stopped = 0,
MTC_Forward,
MTC_Backward
};
MTC_FPS mtc_fps() const { return _mtc_fps; }
MTC_Status mtc_running() const { return _mtc_running; }
const byte *mtc_current() const { return _mtc_time; }

View File

@ -226,7 +226,7 @@ Parser::process_mtc_quarter_frame (byte *msg)
/* time code is looking good */
#ifdef DEBUG_MTC
cerr << "for quarter frame " << which_quarter_frame << " byte = " << hex << (int) msg[1] << dec << endl;
// cerr << "for quarter frame " << which_quarter_frame << " byte = " << hex << (int) msg[1] << dec << endl;
#endif
switch (which_quarter_frame) {
@ -276,6 +276,10 @@ Parser::process_mtc_quarter_frame (byte *msg)
}
#ifdef DEBUG_MTC
cerr << "Emit MTC Qtr\n";
#endif
mtc_qtr (*this, which_quarter_frame, _timestamp); /* EMIT_SIGNAL */
// mtc (*this, &msg[1], msglen - 1);