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/tempo.h"
49 #include "ardour/operations.h"
54 using namespace ARDOUR;
58 Session::add_post_transport_work (PostTransportWork ptw)
60 PostTransportWork oldval;
61 PostTransportWork newval;
65 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
66 newval = PostTransportWork (oldval | ptw);
67 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
73 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
77 Session::request_input_change_handling ()
79 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
80 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
86 Session::request_sync_source (Slave* new_slave)
88 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
91 seamless = Config->get_seamless_loop ();
93 if (dynamic_cast<Engine_Slave*>(new_slave)) {
94 /* JACK cannot support seamless looping at present */
95 Config->set_seamless_loop (false);
97 /* reset to whatever the value was before we last switched slaves */
98 Config->set_seamless_loop (_was_seamless);
101 /* save value of seamless from before the switch */
102 _was_seamless = seamless;
104 ev->slave = new_slave;
105 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
110 Session::request_transport_speed (double speed, bool as_default)
112 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
113 ev->third_yes_or_no = as_default; // as_default
114 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
118 /** Request a new transport speed, but if the speed parameter is exactly zero then use
119 * a very small +ve value to prevent the transport actually stopping. This method should
120 * be used by callers who are varying transport speed but don't ever want to stop it.
123 Session::request_transport_speed_nonzero (double speed, bool as_default)
129 request_transport_speed (speed, as_default);
133 Session::request_track_speed (Track* tr, double speed)
135 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
141 Session::request_stop (bool abort, bool clear_state)
143 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
144 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));
149 Session::request_locate (framepos_t target_frame, bool with_roll)
151 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
152 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
157 Session::force_locate (framepos_t target_frame, bool with_roll)
159 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
160 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
165 Session::unset_preroll_record_punch ()
167 if (_preroll_record_punch_pos >= 0) {
168 remove_event (_preroll_record_punch_pos, SessionEvent::RecordStart);
170 _preroll_record_punch_pos = -1;
174 Session::request_preroll_record_punch (framepos_t rec_in, framecnt_t preroll)
176 if (actively_recording ()) {
179 unset_preroll_record_punch ();
180 framepos_t start = std::max ((framepos_t)0, rec_in - preroll);
182 _preroll_record_punch_pos = rec_in;
183 if (_preroll_record_punch_pos >= 0) {
184 replace_event (SessionEvent::RecordStart, _preroll_record_punch_pos);
185 config.set_punch_in (false);
186 config.set_punch_out (false);
188 maybe_enable_record ();
189 request_locate (start, true);
190 set_requested_return_frame (rec_in);
194 Session::request_play_loop (bool yn, bool change_transport_roll)
197 // don't attempt to loop when not using Internal Transport
198 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
203 Location *location = _locations->auto_loop_location();
206 if (location == 0 && yn) {
207 error << _("Cannot loop - no loop range defined")
212 if (change_transport_roll) {
213 if (transport_rolling()) {
214 /* start looping at current speed */
215 target_speed = transport_speed ();
217 /* currently stopped */
219 /* start looping at normal speed */
226 /* leave the speed alone */
227 target_speed = transport_speed ();
230 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
231 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
235 if (!change_transport_roll) {
236 if (!transport_rolling()) {
237 /* we're not changing transport state, but we do want
238 to set up position for the new loop. Don't
239 do this if we're rolling already.
241 request_locate (location->start(), false);
245 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
246 // request an immediate locate to refresh the tracks
247 // after disabling looping
248 request_locate (_transport_frame-1, false);
254 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
256 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
258 ev->audio_range = *range;
260 ev->audio_range.clear ();
262 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
267 Session::request_cancel_play_range ()
269 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
275 Session::realtime_stop (bool abort, bool clear_state)
277 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
278 PostTransportWork todo = PostTransportWork (0);
280 /* assume that when we start, we'll be moving forwards */
282 if (_transport_speed < 0.0f) {
283 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
284 _default_transport_speed = 1.0;
286 todo = PostTransportWork (todo | PostTransportStop);
291 boost::shared_ptr<RouteList> r = routes.reader ();
293 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
294 (*i)->realtime_handle_transport_stopped ();
297 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
299 /* the duration change is not guaranteed to have happened, but is likely */
301 todo = PostTransportWork (todo | PostTransportDuration);
304 todo = PostTransportWork (todo | PostTransportAbort);
308 todo = PostTransportWork (todo | PostTransportClearSubstate);
312 add_post_transport_work (todo);
315 _clear_event_type (SessionEvent::StopOnce);
316 _clear_event_type (SessionEvent::RangeStop);
317 _clear_event_type (SessionEvent::RangeLocate);
319 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
320 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
322 if (clear_state && !Config->get_loop_is_mode()) {
326 reset_slave_state ();
328 _transport_speed = 0;
329 _target_transport_speed = 0;
331 g_atomic_int_set (&_playback_load, 100);
332 g_atomic_int_set (&_capture_load, 100);
334 if (config.get_use_video_sync()) {
335 waiting_for_sync_offset = true;
338 transport_sub_state = 0;
342 Session::realtime_locate ()
344 boost::shared_ptr<RouteList> r = routes.reader ();
345 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
346 (*i)->realtime_locate ();
351 Session::butler_transport_work ()
353 /* Note: this function executes in the butler thread context */
357 PostTransportWork ptw;
358 boost::shared_ptr<RouteList> r = routes.reader ();
361 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
363 ptw = post_transport_work();
365 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
368 if (ptw & PostTransportLocate) {
370 if (get_play_loop() && !Config->get_seamless_loop()) {
372 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
374 /* this locate might be happening while we are
377 * Non-seamless looping will require a locate (below) that
378 * will reset capture buffers and throw away data.
380 * Rather than first find all tracks and see if they
381 * have outstanding data, just do a flush anyway. It
382 * may be cheaper this way anyway, and is certainly
386 bool more_disk_io_to_do = false;
390 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
396 if (more_disk_io_to_do) {
405 if (ptw & PostTransportAdjustPlaybackBuffering) {
406 /* non_realtime_locate() calls Automatable::transport_located()
407 * for every route. This eventually calls
408 * ARDOUR::AutomationList::state () which has a LocaleGuard,
409 * and would switch locales forth/back every time.
412 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
413 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
415 tr->adjust_playback_buffering ();
416 /* and refill those buffers ... */
418 (*i)->non_realtime_locate (_transport_frame);
423 if (ptw & PostTransportAdjustCaptureBuffering) {
424 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
425 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
427 tr->adjust_capture_buffering ();
432 if (ptw & PostTransportCurveRealloc) {
433 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
434 (*i)->curve_reallocate();
438 if (ptw & PostTransportInputChange) {
439 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
440 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
442 tr->non_realtime_input_change ();
447 if (ptw & PostTransportSpeed) {
448 non_realtime_set_speed ();
451 if (ptw & PostTransportReverse) {
454 cumulative_rf_motion = 0;
457 /* don't seek if locate will take care of that in non_realtime_stop() */
459 if (!(ptw & PostTransportLocate)) {
460 LocaleGuard lg; // see note for non_realtime_locate() above
461 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
462 (*i)->non_realtime_locate (_transport_frame);
464 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
465 /* new request, stop seeking, and start again */
466 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
473 if (ptw & PostTransportLocate) {
474 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
475 non_realtime_locate ();
478 if (ptw & PostTransportStop) {
479 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
481 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
486 if (ptw & PostTransportOverWrite) {
487 non_realtime_overwrite (on_entry, finished);
489 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
494 if (ptw & PostTransportAudition) {
495 non_realtime_set_audition ();
498 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
500 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
501 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
505 Session::non_realtime_set_speed ()
507 boost::shared_ptr<RouteList> rl = routes.reader();
508 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
509 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
511 tr->non_realtime_set_speed ();
517 Session::non_realtime_overwrite (int on_entry, bool& finished)
519 boost::shared_ptr<RouteList> rl = routes.reader();
520 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
521 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
522 if (tr && tr->pending_overwrite ()) {
523 tr->overwrite_existing_buffers ();
525 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
534 Session::non_realtime_locate ()
536 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
538 if (Config->get_loop_is_mode() && get_play_loop()) {
540 Location *loc = _locations->auto_loop_location();
542 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
543 /* jumped out of loop range: stop tracks from looping,
544 but leave loop (mode) enabled.
546 set_track_loop (false);
548 } else if (loc && Config->get_seamless_loop() &&
549 ((loc->start() <= _transport_frame) ||
550 (loc->end() > _transport_frame) ) ) {
552 /* jumping to start of loop. This might have been done before but it is
553 * idempotent and cheap. Doing it here ensures that when we start playback
554 * outside the loop we still flip tracks into the magic seamless mode
557 set_track_loop (true);
560 set_track_loop (false);
565 /* no more looping .. should have been noticed elsewhere */
570 LocaleGuard lg; // see note for non_realtime_locate() above
571 boost::shared_ptr<RouteList> rl = routes.reader();
572 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
573 (*i)->non_realtime_locate (_transport_frame);
577 _scene_changer->locate (_transport_frame);
579 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
580 rather than clearing them so that the RT thread has to spend time constructing
581 them (in Session::click).
586 #ifdef USE_TRACKS_CODE_FEATURES
588 Session::select_playhead_priority_target (framepos_t& jump_to)
592 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
598 if (Profile->get_trx() && transport_rolling() ) {
599 // We're playing, so do nothing.
600 // Next stop will put us where we need to be.
604 /* Note that the order of checking each AutoReturnTarget flag defines
605 the priority each flag.
607 Ardour/Mixbus: Last Locate
612 Tracks: Range Selection
618 if (autoreturn & RangeSelectionStart) {
619 if (!_range_selection.empty()) {
620 jump_to = _range_selection.from;
622 if (transport_rolling ()) {
623 /* Range selection no longer exists, but we're playing,
624 so do nothing. Next stop will put us where
632 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
633 /* don't try to handle loop play when synced to JACK */
635 if (!synced_to_engine()) {
636 Location *location = _locations->auto_loop_location();
639 jump_to = location->start();
641 if (Config->get_seamless_loop()) {
642 /* need to get track buffers reloaded */
643 set_track_loop (true);
649 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
650 if (!_object_selection.empty()) {
651 jump_to = _object_selection.from;
655 if (jump_to < 0 && (autoreturn & LastLocate)) {
656 jump_to = _last_roll_location;
664 Session::select_playhead_priority_target (framepos_t& jump_to)
666 if (config.get_external_sync() || !config.get_auto_return()) {
670 jump_to = _last_roll_location;
677 Session::follow_playhead_priority ()
681 if (select_playhead_priority_target (target)) {
682 request_locate (target);
687 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
693 PostTransportWork ptw = post_transport_work();
698 boost::shared_ptr<RouteList> rl = routes.reader();
699 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
700 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
701 if (tr && tr->get_captured_frames () != 0) {
707 /* stop and locate are merged here because they share a lot of common stuff */
710 now = localtime (&xnow);
713 auditioner->cancel_audition ();
716 cumulative_rf_motion = 0;
720 begin_reversible_command (Operations::capture);
721 _have_captured = true;
724 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
726 if (abort && did_record) {
727 /* no reason to save the session file when we remove sources
729 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
732 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
733 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
735 tr->transport_stopped_wallclock (*now, xnow, abort);
739 if (abort && did_record) {
740 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
743 boost::shared_ptr<RouteList> r = routes.reader ();
745 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
746 if (!(*i)->is_auditioner()) {
747 (*i)->set_pending_declick (0);
752 commit_reversible_command ();
753 /* increase take name */
754 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
755 string newname = config.get_take_name();
756 config.set_take_name(bump_name_number (newname));
760 if (_engine.running()) {
761 PostTransportWork ptw = post_transport_work ();
762 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
763 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
765 update_latency_compensation ();
768 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
770 if (auto_return_enabled ||
771 (ptw & PostTransportLocate) ||
772 (_requested_return_frame >= 0) ||
773 synced_to_engine()) {
775 if (pending_locate_flush) {
776 flush_all_inserts ();
779 // rg: what is the logic behind this case?
780 // _requested_return_frame should be ignored when synced_to_engine/slaved.
781 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
783 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
784 !(ptw & PostTransportLocate)) {
786 /* no explicit locate queued */
788 bool do_locate = false;
790 if (_requested_return_frame >= 0) {
792 /* explicit return request pre-queued in event list. overrides everything else */
794 _transport_frame = _requested_return_frame;
800 if (select_playhead_priority_target (jump_to)) {
802 _transport_frame = jump_to;
807 _transport_frame = _last_roll_location;
812 _requested_return_frame = -1;
815 _engine.transport_locate (_transport_frame);
823 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
826 if (ptw & PostTransportClearSubstate) {
828 if (!Config->get_loop_is_mode()) {
833 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
836 LocaleGuard lg; // see note for non_realtime_locate() above
837 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
838 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
839 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
840 (*i)->non_realtime_locate (_transport_frame);
842 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
844 /* we will be back */
852 /* don't bother with this stuff if we're disconnected from the engine,
853 because there will be no process callbacks to deliver stuff from
856 if (_engine.connected() && !_engine.freewheeling()) {
857 // need to queue this in the next RT cycle
858 _send_timecode_update = true;
860 if (!dynamic_cast<MTC_Slave*>(_slave)) {
861 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
863 /* This (::non_realtime_stop()) gets called by main
864 process thread, which will lead to confusion
865 when calling AsyncMIDIPort::write().
867 Something must be done. XXX
869 send_mmc_locate (_transport_frame);
873 if ((ptw & PostTransportLocate) && get_record_enabled()) {
874 /* This is scheduled by realtime_stop(), which is also done
875 * when a slave requests /locate/ for an initial sync.
876 * We can't hold up the slave for long with a save() here,
877 * without breaking its initial sync cycle.
879 * save state only if there's no slave or if it's not yet locked.
881 if (!_slave || !_slave->locked()) {
882 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
883 SaveSessionRequested (_current_snapshot_name);
888 /* always try to get rid of this */
890 remove_pending_capture_state ();
892 /* save the current state of things if appropriate */
894 if (did_record && !saved) {
895 SaveSessionRequested (_current_snapshot_name);
898 if (ptw & PostTransportStop) {
900 if (!Config->get_loop_is_mode()) {
905 PositionChanged (_transport_frame); /* EMIT SIGNAL */
906 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
907 TransportStateChange (); /* EMIT SIGNAL */
909 /* and start it up again if relevant */
911 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
912 request_transport_speed (1.0);
915 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
916 around for next time.
918 pending_locate_roll = false;
922 Session::check_declick_out ()
924 bool locate_required = transport_sub_state & PendingLocate;
926 /* this is called after a process() iteration. if PendingDeclickOut was set,
927 it means that we were waiting to declick the output (which has just been
928 done) before maybe doing something else. this is where we do that "something else".
930 note: called from the audio thread.
933 if (transport_sub_state & PendingDeclickOut) {
935 if (locate_required) {
936 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
937 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
939 if (!(transport_sub_state & StopPendingCapture)) {
940 stop_transport (pending_abort);
941 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
945 } else if (transport_sub_state & PendingLoopDeclickOut) {
946 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
947 transport_sub_state &= ~PendingLoopDeclickOut;
952 Session::unset_play_loop ()
956 clear_events (SessionEvent::AutoLoop);
957 clear_events (SessionEvent::AutoLoopDeclick);
958 set_track_loop (false);
961 if (Config->get_seamless_loop()) {
962 /* likely need to flush track buffers: this will locate us to wherever we are */
963 add_post_transport_work (PostTransportLocate);
964 _butler->schedule_transport_work ();
970 Session::set_track_loop (bool yn)
972 Location* loc = _locations->auto_loop_location ();
978 boost::shared_ptr<RouteList> rl = routes.reader ();
980 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
981 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
982 if (tr && !tr->hidden()) {
983 tr->set_loop (yn ? loc : 0);
989 Session::set_play_loop (bool yn, double speed)
991 /* Called from event-handling context */
995 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
996 /* nothing to do, or can't change loop status while recording */
1000 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1001 warning << string_compose (
1002 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1003 "Recommend changing the configured options"), PROGRAM_NAME)
1011 have_looped = false;
1015 unset_play_range ();
1017 if (Config->get_seamless_loop()) {
1018 if (!Config->get_loop_is_mode()) {
1019 /* set all tracks to use internal looping */
1020 set_track_loop (true);
1022 /* we will do this in the locate to the start OR when we hit the end
1023 * of the loop for the first time
1027 /* set all tracks to NOT use internal looping */
1028 set_track_loop (false);
1031 /* Put the delick and loop events in into the event list. The declick event will
1032 cause a de-clicking fade-out just before the end of the loop, and it will also result
1033 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1038 auto_loop_declick_range (loc, dcp, dcl);
1039 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1040 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1042 /* if requested to roll, locate to start of loop and
1043 * roll but ONLY if we're not already rolling.
1045 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1048 if (Config->get_loop_is_mode()) {
1049 /* loop IS a transport mode: if already
1050 rolling, do not locate to loop start.
1052 if (!transport_rolling() && (speed != 0.0)) {
1053 start_locate (loc->start(), true, true, false, true);
1057 start_locate (loc->start(), true, true, false, true);
1067 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1068 TransportStateChange ();
1071 Session::flush_all_inserts ()
1073 boost::shared_ptr<RouteList> r = routes.reader ();
1075 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1076 (*i)->flush_processors ();
1081 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1083 if (target_frame < 0) {
1084 error << _("Locate called for negative sample position - ignored") << endmsg;
1088 if (synced_to_engine()) {
1093 _slave->speed_and_position (sp, pos);
1095 if (target_frame != pos) {
1097 if (config.get_jack_time_master()) {
1098 /* actually locate now, since otherwise jack_timebase_callback
1099 will use the incorrect _transport_frame and report an old
1100 and incorrect time to Jack transport
1102 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1105 /* tell JACK to change transport position, and we will
1106 follow along later in ::follow_slave()
1109 _engine.transport_locate (target_frame);
1111 if (sp != 1.0f && with_roll) {
1112 _engine.transport_start ();
1118 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1123 Session::micro_locate (framecnt_t distance)
1125 boost::shared_ptr<RouteList> rl = routes.reader();
1126 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1127 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1128 if (tr && !tr->can_internal_playback_seek (distance)) {
1133 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1134 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1136 tr->internal_playback_seek (distance);
1140 _transport_frame += distance;
1144 /** @param with_mmc true to send a MMC locate command when the locate is done */
1146 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1148 bool need_butler = false;
1150 /* Locates for seamless looping are fairly different from other
1151 * locates. They assume that the diskstream buffers for each track
1152 * already have the correct data in them, and thus there is no need to
1153 * actually tell the tracks to locate. What does need to be done,
1154 * though, is all the housekeeping that is associated with non-linear
1155 * changes in the value of _transport_frame.
1158 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1159 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1161 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1163 /* already at the desired position. Not forced to locate,
1164 the loop isn't changing, so unless we're told to
1165 start rolling also, there's nothing to do but
1166 tell the world where we are (again).
1170 set_transport_speed (1.0, 0, false);
1172 loop_changing = false;
1173 Located (); /* EMIT SIGNAL */
1177 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1178 /* Schedule a declick. We'll be called again when its done.
1179 We only do it this way for ordinary locates, not those
1180 due to **seamless** loops.
1183 if (!(transport_sub_state & PendingDeclickOut)) {
1184 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1185 pending_locate_frame = target_frame;
1186 pending_locate_roll = with_roll;
1187 pending_locate_flush = with_flush;
1192 // Update Timecode time
1193 _transport_frame = target_frame;
1194 _last_roll_or_reversal_location = target_frame;
1195 timecode_time(_transport_frame, transmitting_timecode_time);
1197 /* do "stopped" stuff if:
1199 * we are rolling AND
1200 * no autoplay in effect AND
1201 * we're not going to keep rolling after the locate AND
1202 * !(playing a loop with JACK sync)
1206 bool transport_was_stopped = !transport_rolling();
1208 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1209 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1210 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1211 transport_was_stopped = true;
1213 /* otherwise tell the world that we located */
1217 if (force || !for_loop_enabled || loop_changing) {
1219 PostTransportWork todo = PostTransportLocate;
1221 if (with_roll && transport_was_stopped) {
1222 todo = PostTransportWork (todo | PostTransportRoll);
1225 add_post_transport_work (todo);
1230 /* this is functionally what clear_clicks() does but with a tentative lock */
1232 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1234 if (clickm.locked()) {
1236 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1245 /* switch from input if we're going to roll */
1246 if (Config->get_monitoring_model() == HardwareMonitoring) {
1247 set_track_monitor_input_status (!config.get_auto_input());
1250 /* otherwise we're going to stop, so do the opposite */
1251 if (Config->get_monitoring_model() == HardwareMonitoring) {
1252 set_track_monitor_input_status (true);
1256 /* cancel looped playback if transport pos outside of loop range */
1259 Location* al = _locations->auto_loop_location();
1262 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1264 // located outside the loop: cancel looping directly, this is called from event handling context
1266 have_looped = false;
1268 if (!Config->get_loop_is_mode()) {
1269 set_play_loop (false, _transport_speed);
1271 if (Config->get_seamless_loop()) {
1272 /* this will make the non_realtime_locate() in the butler
1273 which then causes seek() in tracks actually do the right
1276 set_track_loop (false);
1280 } else if (_transport_frame == al->start()) {
1282 // located to start of loop - this is looping, basically
1286 if (_last_roll_location != al->start()) {
1287 /* didn't start at loop start - playback must have
1288 * started before loop since we've now hit the loop
1291 add_post_transport_work (PostTransportLocate);
1297 boost::shared_ptr<RouteList> rl = routes.reader();
1299 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1300 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1302 if (tr && tr->rec_enable_control()->get_value()) {
1303 // tell it we've looped, so it can deal with the record state
1304 tr->transport_looped (_transport_frame);
1309 TransportLooped(); // EMIT SIGNAL
1315 _butler->schedule_transport_work ();
1318 loop_changing = false;
1320 _send_timecode_update = true;
1323 send_mmc_locate (_transport_frame);
1326 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1327 Located (); /* EMIT SIGNAL */
1330 /** Set the transport speed.
1331 * Called from the process thread.
1332 * @param speed New speed
1335 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1337 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1338 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1340 if (_transport_speed == speed) {
1341 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1342 _default_transport_speed = 1.0;
1347 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1348 /* no varispeed during recording */
1349 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1350 _transport_speed, _transport_frame));
1354 _target_transport_speed = fabs(speed);
1356 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1357 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1361 speed = min (8.0, speed);
1362 } else if (speed < 0) {
1363 speed = max (-8.0, speed);
1366 if (transport_rolling() && speed == 0.0) {
1368 /* we are rolling and we want to stop */
1370 if (Config->get_monitoring_model() == HardwareMonitoring) {
1371 set_track_monitor_input_status (true);
1374 if (synced_to_engine ()) {
1376 /* do this here because our response to the slave won't
1379 _play_range = false;
1382 _engine.transport_stop ();
1384 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1386 if (!auto_return_enabled) {
1387 _requested_return_frame = destination_frame;
1390 stop_transport (abort);
1393 } else if (transport_stopped() && speed == 1.0) {
1395 _default_transport_speed = speed;
1397 /* we are stopped and we want to start rolling at speed 1 */
1399 if (Config->get_loop_is_mode() && play_loop) {
1401 Location *location = _locations->auto_loop_location();
1403 if (location != 0) {
1404 if (_transport_frame != location->start()) {
1406 if (Config->get_seamless_loop()) {
1407 /* force tracks to do their thing */
1408 set_track_loop (true);
1411 /* jump to start and then roll from there */
1413 request_locate (location->start(), true);
1419 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1420 set_track_monitor_input_status (false);
1423 if (synced_to_engine()) {
1424 _engine.transport_start ();
1431 /* not zero, not 1.0 ... varispeed */
1433 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1434 warning << string_compose (
1435 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1441 if (actively_recording()) {
1445 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1449 if (speed < 0.0 && _transport_frame == 0) {
1455 /* if we are reversing relative to the current speed, or relative to the speed
1456 before the last stop, then we have to do extra work.
1459 PostTransportWork todo = PostTransportWork (0);
1461 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1462 todo = PostTransportWork (todo | PostTransportReverse);
1463 _last_roll_or_reversal_location = _transport_frame;
1466 _last_transport_speed = _transport_speed;
1467 _transport_speed = speed;
1470 _default_transport_speed = speed;
1473 boost::shared_ptr<RouteList> rl = routes.reader();
1474 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1475 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1476 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1477 todo = PostTransportWork (todo | PostTransportSpeed);
1482 add_post_transport_work (todo);
1483 _butler->schedule_transport_work ();
1486 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1488 /* throttle signal emissions.
1489 * when slaved [_last]_transport_speed
1490 * usually changes every cycle (tiny amounts due to DLL).
1491 * Emitting a signal every cycle is overkill and unwarranted.
1493 * Using _last_transport_speed is not acceptable,
1494 * since it allows for large changes over a long period
1495 * of time. Hence we introduce a dedicated variable to keep track
1497 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1498 * for TransportStateChange() here is the ShuttleControl display.
1500 if (fabs (_signalled_varispeed - speed) > .002
1501 // still, signal hard changes to 1.0 and 0.0:
1502 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1503 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1506 TransportStateChange (); /* EMIT SIGNAL */
1507 _signalled_varispeed = speed;
1513 /** Stop the transport. */
1515 Session::stop_transport (bool abort, bool clear_state)
1517 if (_transport_speed == 0.0f) {
1521 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1523 if (!get_transport_declick_required()) {
1525 /* stop has not yet been scheduled */
1527 boost::shared_ptr<RouteList> rl = routes.reader();
1528 framepos_t stop_target = audible_frame();
1530 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1531 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1533 tr->prepare_to_stop (_transport_frame, stop_target);
1539 if (actively_recording() && /* we are recording */
1540 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1542 /* we need to capture the audio that is still somewhere in the pipeline between
1543 wherever it was generated and the process callback. This means that even though
1544 the user (or something else) has asked us to stop, we have to roll
1545 past this point and then reset the playhead/transport location to
1546 the position at which the stop was requested.
1548 we still need playback to "stop" now, however, which is why we schedule
1552 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1553 _transport_frame, _worst_input_latency,
1554 _transport_frame + _worst_input_latency,
1557 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1558 _transport_frame + _worst_input_latency,
1563 /* request a declick at the start of the next process cycle() so that playback ceases.
1564 It will remain silent until we actually stop (at the StopOnce event somewhere in
1565 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1566 does not stop the transport too early.
1568 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1572 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1574 new_bits = PendingDeclickOut;
1575 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1578 /* we'll be called again after the declick */
1579 transport_sub_state = SubState (transport_sub_state|new_bits);
1580 pending_abort = abort;
1586 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1588 /* declick was scheduled, but we've been called again, which means it is really time to stop
1590 XXX: we should probably split this off into its own method and call it explicitly.
1593 realtime_stop (abort, clear_state);
1594 _butler->schedule_transport_work ();
1598 /** Called from the process thread */
1600 Session::start_transport ()
1602 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1604 _last_roll_location = _transport_frame;
1605 _last_roll_or_reversal_location = _transport_frame;
1607 have_looped = false;
1609 /* if record status is Enabled, move it to Recording. if its
1610 already Recording, move it to Disabled.
1613 switch (record_status()) {
1615 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1622 disable_record (false);
1630 transport_sub_state |= PendingDeclickIn;
1632 _transport_speed = _default_transport_speed;
1633 _target_transport_speed = _transport_speed;
1635 boost::shared_ptr<RouteList> rl = routes.reader();
1636 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1637 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1639 tr->realtime_set_speed (tr->speed(), true);
1643 if (!_engine.freewheeling()) {
1644 Timecode::Time time;
1645 timecode_time_subframes (_transport_frame, time);
1646 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1647 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1650 if (actively_recording() && click_data && config.get_count_in ()) {
1651 /* calculate count-in duration (in audio samples)
1652 * - use [fixed] tempo/meter at _transport_frame
1653 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1655 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1656 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1658 double div = meter.divisions_per_bar ();
1659 double pulses = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * div / 4.0;
1660 double beats_left = fmod (pulses, div);
1662 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1664 double dt = _count_in_samples / div;
1665 if (beats_left == 0) {
1666 /* at bar boundary, count-in 2 bars before start. */
1667 _count_in_samples *= 2;
1669 /* beats left after full bar until roll position */
1670 _count_in_samples += meter.frames_per_grid (tempo, _current_frame_rate) * beats_left;
1674 framepos_t cf = _transport_frame - _count_in_samples;
1675 while (cf < _transport_frame) {
1676 add_click (cf - _worst_track_latency, clickbeat == 0);
1678 clickbeat = fmod (clickbeat + 1, div);
1683 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1684 TransportStateChange (); /* EMIT SIGNAL */
1687 /** Do any transport work in the audio thread that needs to be done after the
1688 * transport thread is finished. Audio thread, realtime safe.
1691 Session::post_transport ()
1693 PostTransportWork ptw = post_transport_work ();
1695 if (ptw & PostTransportAudition) {
1696 if (auditioner && auditioner->auditioning()) {
1697 process_function = &Session::process_audition;
1699 process_function = &Session::process_with_events;
1703 if (ptw & PostTransportStop) {
1705 transport_sub_state = 0;
1708 if (ptw & PostTransportLocate) {
1710 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1713 transport_sub_state = 0;
1718 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1721 set_post_transport_work (PostTransportWork (0));
1725 Session::reset_rf_scale (framecnt_t motion)
1727 cumulative_rf_motion += motion;
1729 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1731 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1733 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1745 Session::mtc_status_changed (bool yn)
1747 g_atomic_int_set (&_mtc_active, yn);
1748 MTCSyncStateChanged( yn );
1752 Session::ltc_status_changed (bool yn)
1754 g_atomic_int_set (&_ltc_active, yn);
1755 LTCSyncStateChanged( yn );
1759 Session::use_sync_source (Slave* new_slave)
1761 /* Runs in process() context */
1763 bool non_rt_required = false;
1765 /* XXX this deletion is problematic because we're in RT context */
1770 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1772 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1773 MTCSyncStateChanged(mtc_slave->locked() );
1775 if (g_atomic_int_get (&_mtc_active) ){
1776 g_atomic_int_set (&_mtc_active, 0);
1777 MTCSyncStateChanged( false );
1779 mtc_status_connection.disconnect ();
1782 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1784 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1785 LTCSyncStateChanged (ltc_slave->locked() );
1787 if (g_atomic_int_get (&_ltc_active) ){
1788 g_atomic_int_set (&_ltc_active, 0);
1789 LTCSyncStateChanged( false );
1791 ltc_status_connection.disconnect ();
1794 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1796 // need to queue this for next process() cycle
1797 _send_timecode_update = true;
1799 boost::shared_ptr<RouteList> rl = routes.reader();
1800 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1801 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1802 if (tr && !tr->hidden()) {
1803 if (tr->realtime_set_speed (tr->speed(), true)) {
1804 non_rt_required = true;
1806 tr->set_slaved (_slave != 0);
1810 if (non_rt_required) {
1811 add_post_transport_work (PostTransportSpeed);
1812 _butler->schedule_transport_work ();
1819 Session::drop_sync_source ()
1821 request_sync_source (0);
1825 Session::switch_to_sync_source (SyncSource src)
1829 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1833 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1838 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1841 catch (failed_constructor& err) {
1847 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1852 new_slave = new LTC_Slave (*this);
1855 catch (failed_constructor& err) {
1862 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1867 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1870 catch (failed_constructor& err) {
1876 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1880 if (config.get_video_pullup() != 0.0f) {
1884 new_slave = new Engine_Slave (*AudioEngine::instance());
1892 request_sync_source (new_slave);
1896 Session::set_track_speed (Track* track, double speed)
1898 if (track->realtime_set_speed (speed, false)) {
1899 add_post_transport_work (PostTransportSpeed);
1900 _butler->schedule_transport_work ();
1906 Session::unset_play_range ()
1908 _play_range = false;
1909 _clear_event_type (SessionEvent::RangeStop);
1910 _clear_event_type (SessionEvent::RangeLocate);
1914 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1918 /* Called from event-processing context */
1920 unset_play_range ();
1922 if (range.empty()) {
1923 /* _play_range set to false in unset_play_range()
1925 if (!leave_rolling) {
1926 /* stop transport */
1927 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1935 /* cancel loop play */
1938 list<AudioRange>::size_type sz = range.size();
1942 list<AudioRange>::iterator i = range.begin();
1943 list<AudioRange>::iterator next;
1945 while (i != range.end()) {
1950 /* locating/stopping is subject to delays for declicking.
1953 framepos_t requested_frame = i->end;
1955 if (requested_frame > current_block_size) {
1956 requested_frame -= current_block_size;
1958 requested_frame = 0;
1961 if (next == range.end()) {
1962 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1964 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1972 } else if (sz == 1) {
1974 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1979 /* save range so we can do auto-return etc. */
1981 current_audio_range = range;
1983 /* now start rolling at the right place */
1985 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1988 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1989 TransportStateChange ();
1993 Session::request_bounded_roll (framepos_t start, framepos_t end)
1995 AudioRange ar (start, end, 0);
1996 list<AudioRange> lar;
1999 request_play_range (&lar, true);
2003 Session::set_requested_return_frame (framepos_t return_to)
2005 _requested_return_frame = return_to;
2009 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2011 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2012 ev->target2_frame = start;
2017 Session::engine_halted ()
2021 /* there will be no more calls to process(), so
2022 we'd better clean up for ourselves, right now.
2024 but first, make sure the butler is out of
2032 realtime_stop (false, true);
2033 non_realtime_stop (false, 0, ignored);
2034 transport_sub_state = 0;
2036 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2037 TransportStateChange (); /* EMIT SIGNAL */
2042 Session::xrun_recovery ()
2046 Xrun (_transport_frame); /* EMIT SIGNAL */
2048 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2050 /* it didn't actually halt, but we need
2051 to handle things in the same way.
2059 Session::route_processors_changed (RouteProcessorChange c)
2061 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2065 if (c.type == RouteProcessorChange::MeterPointChange) {
2070 if (c.type == RouteProcessorChange::RealTimeChange) {
2075 update_latency_compensation ();
2082 Session::allow_auto_play (bool yn)
2084 auto_play_legal = yn;
2088 Session::maybe_stop (framepos_t limit)
2090 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2091 if (synced_to_engine () && config.get_jack_time_master ()) {
2092 _engine.transport_stop ();
2093 } else if (!synced_to_engine ()) {
2102 Session::send_mmc_locate (framepos_t t)
2108 if (!_engine.freewheeling()) {
2109 Timecode::Time time;
2110 timecode_time_subframes (t, time);
2111 send_immediate_mmc (MIDI::MachineControlCommand (time));
2115 /** Ask the transport to not send timecode until further notice. The suspension
2116 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2117 * should be checked by the caller to find out when.
2120 Session::request_suspend_timecode_transmission ()
2122 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2127 Session::request_resume_timecode_transmission ()
2129 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2134 Session::timecode_transmission_suspended () const
2136 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;