_was_seamless = seamless;
ev->slave = new_slave;
+ DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
queue_event (ev);
}
if (_transport_speed < 0.0f) {
todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
+ _default_transport_speed = 1.0;
} else {
todo = PostTransportWork (todo | PostTransportStop);
}
if (tr) {
tr->adjust_playback_buffering ();
/* and refill those buffers ... */
- tr->non_realtime_locate (_transport_frame);
}
+ (*i)->non_realtime_locate (_transport_frame);
}
}
if (!(ptw & PostTransportLocate)) {
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
- if (tr && !tr->hidden()) {
- tr->non_realtime_locate (_transport_frame);
- }
+ (*i)->non_realtime_locate (_transport_frame);
+
if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
/* new request, stop seeking, and start again */
g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
+ DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
}
void
{
boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
- boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
- if (tr) {
- tr->non_realtime_locate (_transport_frame);
- }
+ (*i)->non_realtime_locate (_transport_frame);
}
/* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_hidden()) {
+ if (!(*i)->is_auditioner()) {
(*i)->set_pending_declick (0);
}
}
DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
- boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
- if (tr && !tr->hidden()) {
- tr->non_realtime_locate (_transport_frame);
- }
+ (*i)->non_realtime_locate (_transport_frame);
if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
finished = false;
}
if ((ptw & PostTransportLocate) && get_record_enabled()) {
- /* capture start has been changed, so save pending state */
- save_state ("", true);
- saved = true;
+ /* This is scheduled by realtime_stop(), which is also done
+ * when a slave requests /locate/ for an initial sync.
+ * We can't hold up the slave for long with a save() here,
+ * without breaking its initial sync cycle.
+ *
+ * save state only if there's no slave or if it's not yet locked.
+ */
+ if (!_slave || !_slave->locked()) {
+ DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: pending save\n"));
+ /* capture start has been changed, so save pending state */
+ save_state ("", true);
+ saved = true;
+ }
}
/* always try to get rid of this */
}
PositionChanged (_transport_frame); /* EMIT SIGNAL */
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
TransportStateChange (); /* EMIT SIGNAL */
/* and start it up again if relevant */
if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
request_transport_speed (1.0);
- pending_locate_roll = false;
}
+
+ /* Even if we didn't do a pending locate roll this time, we don't want it hanging
+ around for next time.
+ */
+ pending_locate_roll = false;
}
void
unset_play_loop ();
}
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
TransportStateChange ();
}
void
if (target_frame != pos) {
+ if (config.get_jack_time_master()) {
+ /* actually locate now, since otherwise jack_timebase_callback
+ will use the incorrect _transport_frame and report an old
+ and incorrect time to Jack transport
+ */
+ locate (target_frame, with_roll, with_flush, with_loop, force);
+ }
+
/* tell JACK to change transport position, and we will
follow along later in ::follow_slave()
*/
* though, is all the housekeeping that is associated with non-linear
* changes in the value of _transport_frame.
*/
-
+
if (actively_recording() && !for_seamless_loop) {
return;
}
// Update Timecode time
// [DR] FIXME: find out exactly where this should go below
_transport_frame = target_frame;
+ _last_roll_or_reversal_location = target_frame;
timecode_time(_transport_frame, transmitting_timecode_time);
outbound_mtc_timecode_frame = _transport_frame;
next_quarter_frame_to_send = 0;
/* this is functionally what clear_clicks() does but with a tentative lock */
- Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
+ Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
if (clickm.locked()) {
send_mmc_locate (_transport_frame);
}
+ _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
Located (); /* EMIT SIGNAL */
}
void
Session::set_transport_speed (double speed, bool abort, bool clear_state, bool as_default)
{
- DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %5\n",
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
if (_transport_speed == speed) {
+ if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
+ _default_transport_speed = 1.0;
+ }
return;
}
if (actively_recording() && speed != 1.0 && speed != 0.0) {
/* no varispeed during recording */
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
+ _transport_speed, _transport_frame));
return;
}
_butler->schedule_transport_work ();
}
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
TransportStateChange (); /* EMIT SIGNAL */
}
}
if (tr) {
tr->realtime_set_speed (tr->speed(), true);
}
- (*i)->automation_snapshot (_transport_frame, true);
}
if (!_engine.freewheeling()) {
}
}
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
TransportStateChange (); /* EMIT SIGNAL */
}
delete _slave;
_slave = new_slave;
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
+
send_full_time_code (_transport_frame);
boost::shared_ptr<RouteList> rl = routes.reader();
}
break;
+ case LTC:
+ if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
+ return;
+ }
+
+ try {
+ new_slave = new LTC_Slave (*this);
+ }
+
+ catch (failed_constructor& err) {
+ return;
+ }
+
+ break;
+
case MIDIClock:
if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
return;
ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
merge_event (ev);
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
TransportStateChange ();
}
non_realtime_stop (false, 0, ignored);
transport_sub_state = 0;
+ DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
TransportStateChange (); /* EMIT SIGNAL */
}