2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libardour-config.h"
29 #include "pbd/error.h"
30 #include "pbd/enumwriter.h"
31 #include "pbd/pthread_utils.h"
32 #include "pbd/memento_command.h"
33 #include "pbd/stacktrace.h"
35 #include "midi++/mmc.h"
36 #include "midi++/port.h"
38 #include "ardour/audioengine.h"
39 #include "ardour/auditioner.h"
40 #include "ardour/butler.h"
41 #include "ardour/click.h"
42 #include "ardour/debug.h"
43 #include "ardour/location.h"
44 #include "ardour/profile.h"
45 #include "ardour/scene_changer.h"
46 #include "ardour/session.h"
47 #include "ardour/slave.h"
48 #include "ardour/operations.h"
53 using namespace ARDOUR;
57 Session::add_post_transport_work (PostTransportWork ptw)
59 PostTransportWork oldval;
60 PostTransportWork newval;
64 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
65 newval = PostTransportWork (oldval | ptw);
66 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
72 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
76 Session::request_input_change_handling ()
78 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
79 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
85 Session::request_sync_source (Slave* new_slave)
87 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
90 seamless = Config->get_seamless_loop ();
92 if (dynamic_cast<Engine_Slave*>(new_slave)) {
93 /* JACK cannot support seamless looping at present */
94 Config->set_seamless_loop (false);
96 /* reset to whatever the value was before we last switched slaves */
97 Config->set_seamless_loop (_was_seamless);
100 /* save value of seamless from before the switch */
101 _was_seamless = seamless;
103 ev->slave = new_slave;
104 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
109 Session::request_transport_speed (double speed, bool as_default)
111 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
112 ev->third_yes_or_no = true;
113 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
117 /** Request a new transport speed, but if the speed parameter is exactly zero then use
118 * a very small +ve value to prevent the transport actually stopping. This method should
119 * be used by callers who are varying transport speed but don't ever want to stop it.
122 Session::request_transport_speed_nonzero (double speed, bool as_default)
128 request_transport_speed (speed, as_default);
132 Session::request_track_speed (Track* tr, double speed)
134 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
140 Session::request_stop (bool abort, bool clear_state)
142 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
143 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, audible %3 transport %4 abort = %1, clear state = %2\n", abort, clear_state, audible_frame(), _transport_frame));
148 Session::request_locate (framepos_t target_frame, bool with_roll)
150 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
151 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
156 Session::force_locate (framepos_t target_frame, bool with_roll)
158 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
159 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
164 Session::request_play_loop (bool yn, bool change_transport_roll)
167 Location *location = _locations->auto_loop_location();
170 if (location == 0 && yn) {
171 error << _("Cannot loop - no loop range defined")
176 if (change_transport_roll) {
177 if (transport_rolling()) {
178 /* start looping at current speed */
179 target_speed = transport_speed ();
181 /* currently stopped */
183 /* start looping at normal speed */
190 /* leave the speed alone */
191 target_speed = transport_speed ();
194 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
195 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
199 if (!change_transport_roll) {
200 if (!transport_rolling()) {
201 /* we're not changing transport state, but we do want
202 to set up position for the new loop. Don't
203 do this if we're rolling already.
205 request_locate (location->start(), false);
209 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
210 // request an immediate locate to refresh the tracks
211 // after disabling looping
212 request_locate (_transport_frame-1, false);
218 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
220 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
222 ev->audio_range = *range;
224 ev->audio_range.clear ();
226 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
231 Session::request_cancel_play_range ()
233 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
239 Session::realtime_stop (bool abort, bool clear_state)
241 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
242 PostTransportWork todo = PostTransportWork (0);
244 /* assume that when we start, we'll be moving forwards */
246 if (_transport_speed < 0.0f) {
247 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
248 _default_transport_speed = 1.0;
250 todo = PostTransportWork (todo | PostTransportStop);
255 boost::shared_ptr<RouteList> r = routes.reader ();
257 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
258 (*i)->realtime_handle_transport_stopped ();
261 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
263 /* the duration change is not guaranteed to have happened, but is likely */
265 todo = PostTransportWork (todo | PostTransportDuration);
268 todo = PostTransportWork (todo | PostTransportAbort);
272 todo = PostTransportWork (todo | PostTransportClearSubstate);
276 add_post_transport_work (todo);
279 _clear_event_type (SessionEvent::StopOnce);
280 _clear_event_type (SessionEvent::RangeStop);
281 _clear_event_type (SessionEvent::RangeLocate);
283 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
284 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
286 reset_slave_state ();
288 _transport_speed = 0;
289 _target_transport_speed = 0;
291 g_atomic_int_set (&_playback_load, 100);
292 g_atomic_int_set (&_capture_load, 100);
294 if (config.get_use_video_sync()) {
295 waiting_for_sync_offset = true;
298 transport_sub_state = 0;
302 Session::realtime_locate ()
304 boost::shared_ptr<RouteList> r = routes.reader ();
305 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
306 (*i)->realtime_locate ();
311 Session::butler_transport_work ()
315 PostTransportWork ptw;
316 boost::shared_ptr<RouteList> r = routes.reader ();
319 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
321 ptw = post_transport_work();
323 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
325 if (ptw & PostTransportAdjustPlaybackBuffering) {
326 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
327 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
329 tr->adjust_playback_buffering ();
330 /* and refill those buffers ... */
332 (*i)->non_realtime_locate (_transport_frame);
337 if (ptw & PostTransportAdjustCaptureBuffering) {
338 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
339 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
341 tr->adjust_capture_buffering ();
346 if (ptw & PostTransportCurveRealloc) {
347 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
348 (*i)->curve_reallocate();
352 if (ptw & PostTransportInputChange) {
353 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
354 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
356 tr->non_realtime_input_change ();
361 if (ptw & PostTransportSpeed) {
362 non_realtime_set_speed ();
365 if (ptw & PostTransportReverse) {
368 cumulative_rf_motion = 0;
371 /* don't seek if locate will take care of that in non_realtime_stop() */
373 if (!(ptw & PostTransportLocate)) {
375 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
376 (*i)->non_realtime_locate (_transport_frame);
378 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
379 /* new request, stop seeking, and start again */
380 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
387 if (ptw & PostTransportLocate) {
388 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
389 non_realtime_locate ();
392 if (ptw & PostTransportStop) {
393 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
395 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
400 if (ptw & PostTransportOverWrite) {
401 non_realtime_overwrite (on_entry, finished);
403 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
408 if (ptw & PostTransportAudition) {
409 non_realtime_set_audition ();
412 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
414 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
415 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
419 Session::non_realtime_set_speed ()
421 boost::shared_ptr<RouteList> rl = routes.reader();
422 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
423 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
425 tr->non_realtime_set_speed ();
431 Session::non_realtime_overwrite (int on_entry, bool& finished)
433 boost::shared_ptr<RouteList> rl = routes.reader();
434 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
435 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
436 if (tr && tr->pending_overwrite ()) {
437 tr->overwrite_existing_buffers ();
439 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
448 Session::non_realtime_locate ()
450 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
452 if (Config->get_loop_is_mode() && get_play_loop()) {
454 Location *loc = _locations->auto_loop_location();
456 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
457 /* jumped out of loop range: stop tracks from looping,
458 but leave loop (mode) enabled.
460 set_track_loop (false);
462 } else if (loc && Config->get_seamless_loop() &&
463 ((loc->start() <= _transport_frame) ||
464 (loc->end() > _transport_frame) ) ) {
466 /* jumping to start of loop. This might have been done before but it is
467 * idempotent and cheap. Doing it here ensures that when we start playback
468 * outside the loop we still flip tracks into the magic seamless mode
471 set_track_loop (true);
474 set_track_loop (false);
479 /* no more looping .. should have been noticed elsewhere */
483 boost::shared_ptr<RouteList> rl = routes.reader();
484 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
485 (*i)->non_realtime_locate (_transport_frame);
488 _scene_changer->locate (_transport_frame);
490 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
491 rather than clearing them so that the RT thread has to spend time constructing
492 them (in Session::click).
498 Session::select_playhead_priority_target (framepos_t& jump_to)
502 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
508 if (Profile->get_trx() && transport_rolling() ) {
509 // We're playing, so do nothing.
510 // Next stop will put us where we need to be.
514 /* Note that the order of checking each AutoReturnTarget flag defines
515 the priority each flag.
517 Ardour/Mixbus: Last Locate
522 Tracks: Range Selection
528 #ifndef USE_TRACKS_CODE_FEATURES
529 if (autoreturn & LastLocate) {
530 jump_to = _last_roll_location;
533 if (jump_to < 0 && (autoreturn & RangeSelectionStart)) {
535 if (autoreturn & RangeSelectionStart) {
537 if (!_range_selection.empty()) {
538 jump_to = _range_selection.from;
540 if (transport_rolling ()) {
541 /* Range selection no longer exists, but we're playing,
542 so do nothing. Next stop will put us where
550 if (jump_to < 0 && (autoreturn & Loop)) {
551 /* don't try to handle loop play when synced to JACK */
553 if (!synced_to_engine()) {
554 Location *location = _locations->auto_loop_location();
557 jump_to = location->start();
559 if (Config->get_seamless_loop()) {
560 /* need to get track buffers reloaded */
561 set_track_loop (true);
567 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
568 if (!_object_selection.empty()) {
569 jump_to = _object_selection.from;
573 #ifdef USE_TRACKS_CODE_FEATURES
574 if (jump_to < 0 && (autoreturn & LastLocate)) {
575 jump_to = _last_roll_location;
583 Session::follow_playhead_priority ()
587 if (select_playhead_priority_target (target)) {
588 request_locate (target);
593 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
599 PostTransportWork ptw = post_transport_work();
604 boost::shared_ptr<RouteList> rl = routes.reader();
605 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
606 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
607 if (tr && tr->get_captured_frames () != 0) {
613 /* stop and locate are merged here because they share a lot of common stuff */
616 now = localtime (&xnow);
619 auditioner->cancel_audition ();
622 cumulative_rf_motion = 0;
626 begin_reversible_command (Operations::capture);
627 _have_captured = true;
630 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
632 if (abort && did_record) {
633 /* no reason to save the session file when we remove sources
635 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
638 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
639 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
641 tr->transport_stopped_wallclock (*now, xnow, abort);
645 if (abort && did_record) {
646 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
649 boost::shared_ptr<RouteList> r = routes.reader ();
651 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
652 if (!(*i)->is_auditioner()) {
653 (*i)->set_pending_declick (0);
658 commit_reversible_command ();
659 /* increase take name */
660 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
661 string newname = config.get_take_name();
662 config.set_take_name(bump_name_number (newname));
666 if (_engine.running()) {
667 PostTransportWork ptw = post_transport_work ();
668 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
669 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
671 update_latency_compensation ();
674 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
676 if (auto_return_enabled ||
677 (ptw & PostTransportLocate) ||
678 (_requested_return_frame >= 0) ||
679 synced_to_engine()) {
681 if (pending_locate_flush) {
682 flush_all_inserts ();
685 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
686 !(ptw & PostTransportLocate)) {
688 /* no explicit locate queued */
690 bool do_locate = false;
692 if (_requested_return_frame >= 0) {
694 /* explicit return request pre-queued in event list. overrides everything else */
696 _transport_frame = _requested_return_frame;
702 if (select_playhead_priority_target (jump_to)) {
704 _transport_frame = jump_to;
709 _transport_frame = _last_roll_location;
714 _requested_return_frame = -1;
717 _engine.transport_locate (_transport_frame);
725 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
728 if (ptw & PostTransportClearSubstate) {
730 if (!Config->get_loop_is_mode()) {
735 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
737 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
738 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
739 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
740 (*i)->non_realtime_locate (_transport_frame);
742 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
744 /* we will be back */
751 /* don't bother with this stuff if we're disconnected from the engine,
752 because there will be no process callbacks to deliver stuff from
755 if (_engine.connected() && !_engine.freewheeling()) {
756 // need to queue this in the next RT cycle
757 _send_timecode_update = true;
759 if (!dynamic_cast<MTC_Slave*>(_slave)) {
760 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
762 /* This (::non_realtime_stop()) gets called by main
763 process thread, which will lead to confusion
764 when calling AsyncMIDIPort::write().
766 Something must be done. XXX
768 send_mmc_locate (_transport_frame);
772 if ((ptw & PostTransportLocate) && get_record_enabled()) {
773 /* This is scheduled by realtime_stop(), which is also done
774 * when a slave requests /locate/ for an initial sync.
775 * We can't hold up the slave for long with a save() here,
776 * without breaking its initial sync cycle.
778 * save state only if there's no slave or if it's not yet locked.
780 if (!_slave || !_slave->locked()) {
781 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
782 SaveSessionRequested (_current_snapshot_name);
787 /* always try to get rid of this */
789 remove_pending_capture_state ();
791 /* save the current state of things if appropriate */
793 if (did_record && !saved) {
794 SaveSessionRequested (_current_snapshot_name);
797 if (ptw & PostTransportStop) {
799 if (!Config->get_loop_is_mode()) {
804 PositionChanged (_transport_frame); /* EMIT SIGNAL */
805 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
806 TransportStateChange (); /* EMIT SIGNAL */
808 /* and start it up again if relevant */
810 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
811 request_transport_speed (1.0);
814 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
815 around for next time.
817 pending_locate_roll = false;
821 Session::check_declick_out ()
823 bool locate_required = transport_sub_state & PendingLocate;
825 /* this is called after a process() iteration. if PendingDeclickOut was set,
826 it means that we were waiting to declick the output (which has just been
827 done) before maybe doing something else. this is where we do that "something else".
829 note: called from the audio thread.
832 if (transport_sub_state & PendingDeclickOut) {
834 if (locate_required) {
835 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
836 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
838 if (!(transport_sub_state & StopPendingCapture)) {
839 stop_transport (pending_abort);
840 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
844 } else if (transport_sub_state & PendingLoopDeclickOut) {
845 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
846 transport_sub_state &= ~PendingLoopDeclickOut;
851 Session::unset_play_loop ()
855 clear_events (SessionEvent::AutoLoop);
856 clear_events (SessionEvent::AutoLoopDeclick);
857 set_track_loop (false);
860 if (Config->get_seamless_loop()) {
861 /* likely need to flush track buffers: this will locate us to wherever we are */
862 add_post_transport_work (PostTransportLocate);
863 _butler->schedule_transport_work ();
869 Session::set_track_loop (bool yn)
871 Location* loc = _locations->auto_loop_location ();
877 boost::shared_ptr<RouteList> rl = routes.reader ();
879 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
880 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
881 if (tr && !tr->hidden()) {
882 tr->set_loop (yn ? loc : 0);
888 Session::set_play_loop (bool yn, double speed)
890 /* Called from event-handling context */
894 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
895 /* nothing to do, or can't change loop status while recording */
899 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
900 warning << string_compose (
901 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
902 "Recommend changing the configured options"), PROGRAM_NAME)
916 if (Config->get_seamless_loop()) {
917 if (!Config->get_loop_is_mode()) {
918 /* set all tracks to use internal looping */
919 set_track_loop (true);
921 /* we will do this in the locate to the start OR when we hit the end
922 * of the loop for the first time
926 /* set all tracks to NOT use internal looping */
927 set_track_loop (false);
930 /* Put the delick and loop events in into the event list. The declick event will
931 cause a de-clicking fade-out just before the end of the loop, and it will also result
932 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
937 auto_loop_declick_range (loc, dcp, dcl);
938 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
939 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
941 /* if requested to roll, locate to start of loop and
942 * roll but ONLY if we're not already rolling.
944 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
947 if (Config->get_loop_is_mode()) {
948 /* loop IS a transport mode: if already
949 rolling, do not locate to loop start.
951 if (!transport_rolling() && (speed != 0.0)) {
952 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
956 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
966 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
967 TransportStateChange ();
970 Session::flush_all_inserts ()
972 boost::shared_ptr<RouteList> r = routes.reader ();
974 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
975 (*i)->flush_processors ();
980 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
982 if (target_frame < 0) {
983 error << _("Locate called for negative sample position - ignored") << endmsg;
987 if (synced_to_engine()) {
992 _slave->speed_and_position (sp, pos);
994 if (target_frame != pos) {
996 if (config.get_jack_time_master()) {
997 /* actually locate now, since otherwise jack_timebase_callback
998 will use the incorrect _transport_frame and report an old
999 and incorrect time to Jack transport
1001 locate (target_frame, with_roll, with_flush, with_loop, force);
1004 /* tell JACK to change transport position, and we will
1005 follow along later in ::follow_slave()
1008 _engine.transport_locate (target_frame);
1010 if (sp != 1.0f && with_roll) {
1011 _engine.transport_start ();
1017 locate (target_frame, with_roll, with_flush, with_loop, force);
1022 Session::micro_locate (framecnt_t distance)
1024 boost::shared_ptr<RouteList> rl = routes.reader();
1025 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1026 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1027 if (tr && !tr->can_internal_playback_seek (distance)) {
1032 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1033 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1035 tr->internal_playback_seek (distance);
1039 _transport_frame += distance;
1043 /** @param with_mmc true to send a MMC locate command when the locate is done */
1045 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_seamless_loop, bool force, bool with_mmc)
1047 bool need_butler = false;
1049 /* Locates for seamless looping are fairly different from other
1050 * locates. They assume that the diskstream buffers for each track
1051 * already have the correct data in them, and thus there is no need to
1052 * actually tell the tracks to locate. What does need to be done,
1053 * though, is all the housekeeping that is associated with non-linear
1054 * changes in the value of _transport_frame.
1057 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 seamless %4 force %5 mmc %6\n",
1058 target_frame, with_roll, with_flush, for_seamless_loop, force, with_mmc));
1060 if (actively_recording() && !for_seamless_loop) {
1064 if (!force && _transport_frame == target_frame && !loop_changing && !for_seamless_loop) {
1066 set_transport_speed (1.0, 0, false);
1068 loop_changing = false;
1069 Located (); /* EMIT SIGNAL */
1073 if (_transport_speed && !for_seamless_loop) {
1074 /* Schedule a declick. We'll be called again when its done.
1075 We only do it this way for ordinary locates, not those
1076 due to **seamless** loops.
1079 if (!(transport_sub_state & PendingDeclickOut)) {
1080 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1081 pending_locate_frame = target_frame;
1082 pending_locate_roll = with_roll;
1083 pending_locate_flush = with_flush;
1088 // Update Timecode time
1089 // [DR] FIXME: find out exactly where this should go below
1090 _transport_frame = target_frame;
1091 _last_roll_or_reversal_location = target_frame;
1092 timecode_time(_transport_frame, transmitting_timecode_time);
1093 outbound_mtc_timecode_frame = _transport_frame;
1094 next_quarter_frame_to_send = 0;
1096 /* do "stopped" stuff if:
1098 * we are rolling AND
1099 * no autoplay in effect AND
1100 * we're not going to keep rolling after the locate AND
1101 * !(playing a loop with JACK sync)
1105 bool transport_was_stopped = !transport_rolling();
1107 if (transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1108 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1109 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1110 transport_was_stopped = true;
1112 /* otherwise tell the world that we located */
1116 if (force || !for_seamless_loop || loop_changing) {
1118 PostTransportWork todo = PostTransportLocate;
1120 if (with_roll && transport_was_stopped) {
1121 todo = PostTransportWork (todo | PostTransportRoll);
1124 add_post_transport_work (todo);
1129 /* this is functionally what clear_clicks() does but with a tentative lock */
1131 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1133 if (clickm.locked()) {
1135 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1144 /* switch from input if we're going to roll */
1145 if (Config->get_monitoring_model() == HardwareMonitoring) {
1146 set_track_monitor_input_status (!config.get_auto_input());
1149 /* otherwise we're going to stop, so do the opposite */
1150 if (Config->get_monitoring_model() == HardwareMonitoring) {
1151 set_track_monitor_input_status (true);
1155 /* cancel looped playback if transport pos outside of loop range */
1158 Location* al = _locations->auto_loop_location();
1161 if (_transport_frame < al->start() || _transport_frame > al->end()) {
1163 // located outside the loop: cancel looping directly, this is called from event handling context
1165 have_looped = false;
1167 if (!Config->get_loop_is_mode()) {
1168 set_play_loop (false, _transport_speed);
1170 if (Config->get_seamless_loop()) {
1171 /* this will make the non_realtime_locate() in the butler
1172 which then causes seek() in tracks actually do the right
1175 set_track_loop (false);
1179 } else if (_transport_frame == al->start()) {
1181 // located to start of loop - this is looping, basically
1183 if (for_seamless_loop) {
1187 if (_last_roll_location != al->start()) {
1188 /* didn't start at loop start - playback must have
1189 * started before loop since we've now hit the loop
1192 add_post_transport_work (PostTransportLocate);
1198 // this is only necessary for seamless looping
1200 boost::shared_ptr<RouteList> rl = routes.reader();
1202 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1203 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1205 if (tr && tr->record_enabled ()) {
1206 // tell it we've looped, so it can deal with the record state
1207 tr->transport_looped (_transport_frame);
1213 TransportLooped(); // EMIT SIGNAL
1219 _butler->schedule_transport_work ();
1222 loop_changing = false;
1224 _send_timecode_update = true;
1227 send_mmc_locate (_transport_frame);
1230 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1231 Located (); /* EMIT SIGNAL */
1234 /** Set the transport speed.
1235 * Called from the process thread.
1236 * @param speed New speed
1239 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1241 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1242 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1244 if (_transport_speed == speed) {
1245 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1246 _default_transport_speed = 1.0;
1251 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1252 /* no varispeed during recording */
1253 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1254 _transport_speed, _transport_frame));
1258 _target_transport_speed = fabs(speed);
1260 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1261 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1265 speed = min (8.0, speed);
1266 } else if (speed < 0) {
1267 speed = max (-8.0, speed);
1270 if (transport_rolling() && speed == 0.0) {
1272 /* we are rolling and we want to stop */
1274 if (Config->get_monitoring_model() == HardwareMonitoring) {
1275 set_track_monitor_input_status (true);
1278 if (synced_to_engine ()) {
1280 /* do this here because our response to the slave won't
1283 _play_range = false;
1286 _engine.transport_stop ();
1288 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1290 if (!auto_return_enabled) {
1291 _requested_return_frame = destination_frame;
1294 stop_transport (abort);
1297 if (!Config->get_loop_is_mode()) {
1301 } else if (transport_stopped() && speed == 1.0) {
1303 /* we are stopped and we want to start rolling at speed 1 */
1305 if (Config->get_loop_is_mode() && play_loop) {
1307 Location *location = _locations->auto_loop_location();
1309 if (location != 0) {
1310 if (_transport_frame != location->start()) {
1312 if (Config->get_seamless_loop()) {
1313 /* force tracks to do their thing */
1314 set_track_loop (true);
1317 /* jump to start and then roll from there */
1319 request_locate (location->start(), true);
1325 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1326 set_track_monitor_input_status (false);
1329 if (synced_to_engine()) {
1330 _engine.transport_start ();
1337 /* not zero, not 1.0 ... varispeed */
1339 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1340 warning << string_compose (
1341 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1347 if (actively_recording()) {
1351 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1355 if (speed < 0.0 && _transport_frame == 0) {
1361 /* if we are reversing relative to the current speed, or relative to the speed
1362 before the last stop, then we have to do extra work.
1365 PostTransportWork todo = PostTransportWork (0);
1367 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1368 todo = PostTransportWork (todo | PostTransportReverse);
1369 _last_roll_or_reversal_location = _transport_frame;
1372 _last_transport_speed = _transport_speed;
1373 _transport_speed = speed;
1376 _default_transport_speed = speed;
1379 boost::shared_ptr<RouteList> rl = routes.reader();
1380 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1381 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1382 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1383 todo = PostTransportWork (todo | PostTransportSpeed);
1388 add_post_transport_work (todo);
1389 _butler->schedule_transport_work ();
1392 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1394 /* throttle signal emissions.
1395 * when slaved [_last]_transport_speed
1396 * usually changes every cycle (tiny amounts due to DLL).
1397 * Emitting a signal every cycle is overkill and unwarranted.
1399 * Using _last_transport_speed is not acceptable,
1400 * since it allows for large changes over a long period
1401 * of time. Hence we introduce a dedicated variable to keep track
1403 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1404 * for TransportStateChange() here is the ShuttleControl display.
1406 if (fabsf(_signalled_varispeed - speed) > .002f
1407 // still, signal hard changes to 1.0 and 0.0:
1408 || ( speed == 1.f && _signalled_varispeed != 1.f)
1409 || ( speed == 0.f && _signalled_varispeed != 0.f)
1412 TransportStateChange (); /* EMIT SIGNAL */
1413 _signalled_varispeed = speed;
1419 /** Stop the transport. */
1421 Session::stop_transport (bool abort, bool clear_state)
1423 if (_transport_speed == 0.0f) {
1427 if (!get_transport_declick_required()) {
1429 /* stop has not yet been scheduled */
1431 boost::shared_ptr<RouteList> rl = routes.reader();
1432 framepos_t stop_target = audible_frame();
1434 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1435 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1437 tr->prepare_to_stop (_transport_frame, stop_target);
1443 if (actively_recording() && /* we are recording */
1444 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1446 /* we need to capture the audio that is still somewhere in the pipeline between
1447 wherever it was generated and the process callback. This means that even though
1448 the user (or something else) has asked us to stop, we have to roll
1449 past this point and then reset the playhead/transport location to
1450 the position at which the stop was requested.
1452 we still need playback to "stop" now, however, which is why we schedule
1456 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1457 _transport_frame, _worst_input_latency,
1458 _transport_frame + _worst_input_latency,
1461 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1462 _transport_frame + _worst_input_latency,
1467 /* request a declick at the start of the next process cycle() so that playback ceases.
1468 It will remain silent until we actually stop (at the StopOnce event somewhere in
1469 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1470 does not stop the transport too early.
1472 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1476 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1478 new_bits = PendingDeclickOut;
1482 /* we'll be called again after the declick */
1483 transport_sub_state = SubState (transport_sub_state|new_bits);
1484 pending_abort = abort;
1490 /* declick was scheduled, but we've been called again, which means it is really time to stop
1492 XXX: we should probably split this off into its own method and call it explicitly.
1495 realtime_stop (abort, clear_state);
1496 _butler->schedule_transport_work ();
1500 /** Called from the process thread */
1502 Session::start_transport ()
1504 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1506 _last_roll_location = _transport_frame;
1507 _last_roll_or_reversal_location = _transport_frame;
1509 have_looped = false;
1511 /* if record status is Enabled, move it to Recording. if its
1512 already Recording, move it to Disabled.
1515 switch (record_status()) {
1517 if (!config.get_punch_in()) {
1524 disable_record (false);
1532 transport_sub_state |= PendingDeclickIn;
1534 _transport_speed = _default_transport_speed;
1535 _target_transport_speed = _transport_speed;
1537 boost::shared_ptr<RouteList> rl = routes.reader();
1538 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1539 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1541 tr->realtime_set_speed (tr->speed(), true);
1545 if (!_engine.freewheeling()) {
1546 Timecode::Time time;
1547 timecode_time_subframes (_transport_frame, time);
1548 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1549 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1553 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1554 TransportStateChange (); /* EMIT SIGNAL */
1557 /** Do any transport work in the audio thread that needs to be done after the
1558 * transport thread is finished. Audio thread, realtime safe.
1561 Session::post_transport ()
1563 PostTransportWork ptw = post_transport_work ();
1565 if (ptw & PostTransportAudition) {
1566 if (auditioner && auditioner->auditioning()) {
1567 process_function = &Session::process_audition;
1569 process_function = &Session::process_with_events;
1573 if (ptw & PostTransportStop) {
1575 transport_sub_state = 0;
1578 if (ptw & PostTransportLocate) {
1580 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1583 transport_sub_state = 0;
1588 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1591 set_post_transport_work (PostTransportWork (0));
1595 Session::reset_rf_scale (framecnt_t motion)
1597 cumulative_rf_motion += motion;
1599 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1601 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1603 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1615 Session::mtc_status_changed (bool yn)
1617 g_atomic_int_set (&_mtc_active, yn);
1618 MTCSyncStateChanged( yn );
1622 Session::use_sync_source (Slave* new_slave)
1624 /* Runs in process() context */
1626 bool non_rt_required = false;
1628 /* XXX this deletion is problematic because we're in RT context */
1633 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1635 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1636 MTCSyncStateChanged(mtc_slave->locked() );
1638 if (g_atomic_int_get (&_mtc_active) ){
1639 g_atomic_int_set (&_mtc_active, 0);
1640 MTCSyncStateChanged( false );
1642 mtc_status_connection.disconnect ();
1645 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1647 // need to queue this for next process() cycle
1648 _send_timecode_update = true;
1650 boost::shared_ptr<RouteList> rl = routes.reader();
1651 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1652 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1653 if (tr && !tr->hidden()) {
1654 if (tr->realtime_set_speed (tr->speed(), true)) {
1655 non_rt_required = true;
1657 tr->set_slaved (_slave != 0);
1661 if (non_rt_required) {
1662 add_post_transport_work (PostTransportSpeed);
1663 _butler->schedule_transport_work ();
1670 Session::drop_sync_source ()
1672 request_sync_source (0);
1676 Session::switch_to_sync_source (SyncSource src)
1680 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1684 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1689 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1692 catch (failed_constructor& err) {
1698 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1703 new_slave = new LTC_Slave (*this);
1706 catch (failed_constructor& err) {
1713 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1718 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1721 catch (failed_constructor& err) {
1727 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1731 if (config.get_video_pullup() != 0.0f) {
1735 new_slave = new Engine_Slave (*AudioEngine::instance());
1743 request_sync_source (new_slave);
1747 Session::set_track_speed (Track* track, double speed)
1749 if (track->realtime_set_speed (speed, false)) {
1750 add_post_transport_work (PostTransportSpeed);
1751 _butler->schedule_transport_work ();
1757 Session::unset_play_range ()
1759 _play_range = false;
1760 _clear_event_type (SessionEvent::RangeStop);
1761 _clear_event_type (SessionEvent::RangeLocate);
1765 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1769 /* Called from event-processing context */
1771 unset_play_range ();
1773 if (range.empty()) {
1774 /* _play_range set to false in unset_play_range()
1776 if (!leave_rolling) {
1777 /* stop transport */
1778 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1786 /* cancel loop play */
1789 list<AudioRange>::size_type sz = range.size();
1793 list<AudioRange>::iterator i = range.begin();
1794 list<AudioRange>::iterator next;
1796 while (i != range.end()) {
1801 /* locating/stopping is subject to delays for declicking.
1804 framepos_t requested_frame = i->end;
1806 if (requested_frame > current_block_size) {
1807 requested_frame -= current_block_size;
1809 requested_frame = 0;
1812 if (next == range.end()) {
1813 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1815 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1823 } else if (sz == 1) {
1825 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1830 /* save range so we can do auto-return etc. */
1832 current_audio_range = range;
1834 /* now start rolling at the right place */
1836 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1839 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1840 TransportStateChange ();
1844 Session::request_bounded_roll (framepos_t start, framepos_t end)
1846 AudioRange ar (start, end, 0);
1847 list<AudioRange> lar;
1850 request_play_range (&lar, true);
1854 Session::set_requested_return_frame (framepos_t return_to)
1856 _requested_return_frame = return_to;
1860 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1862 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1863 ev->target2_frame = start;
1868 Session::engine_halted ()
1872 /* there will be no more calls to process(), so
1873 we'd better clean up for ourselves, right now.
1875 but first, make sure the butler is out of
1883 realtime_stop (false, true);
1884 non_realtime_stop (false, 0, ignored);
1885 transport_sub_state = 0;
1887 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
1888 TransportStateChange (); /* EMIT SIGNAL */
1893 Session::xrun_recovery ()
1897 Xrun (_transport_frame); /* EMIT SIGNAL */
1899 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1901 /* it didn't actually halt, but we need
1902 to handle things in the same way.
1910 Session::route_processors_changed (RouteProcessorChange c)
1912 if (ignore_route_processor_changes) {
1916 if (c.type == RouteProcessorChange::MeterPointChange) {
1921 if (c.type == RouteProcessorChange::RealTimeChange) {
1926 update_latency_compensation ();
1933 Session::allow_auto_play (bool yn)
1935 auto_play_legal = yn;
1939 Session::maybe_stop (framepos_t limit)
1941 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1942 if (synced_to_engine () && config.get_jack_time_master ()) {
1943 _engine.transport_stop ();
1944 } else if (!synced_to_engine ()) {
1953 Session::send_mmc_locate (framepos_t t)
1959 if (!_engine.freewheeling()) {
1960 Timecode::Time time;
1961 timecode_time_subframes (t, time);
1962 send_immediate_mmc (MIDI::MachineControlCommand (time));
1966 /** Ask the transport to not send timecode until further notice. The suspension
1967 * will come into effect some finite time after this call, and timecode_transmission_suspended()
1968 * should be checked by the caller to find out when.
1971 Session::request_suspend_timecode_transmission ()
1973 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1978 Session::request_resume_timecode_transmission ()
1980 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1985 Session::timecode_transmission_suspended () const
1987 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;