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/automation_watch.h"
41 #include "ardour/butler.h"
42 #include "ardour/click.h"
43 #include "ardour/debug.h"
44 #include "ardour/location.h"
45 #include "ardour/profile.h"
46 #include "ardour/scene_changer.h"
47 #include "ardour/session.h"
48 #include "ardour/slave.h"
49 #include "ardour/tempo.h"
50 #include "ardour/operations.h"
55 using namespace ARDOUR;
59 Session::add_post_transport_work (PostTransportWork ptw)
61 PostTransportWork oldval;
62 PostTransportWork newval;
66 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
67 newval = PostTransportWork (oldval | ptw);
68 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
74 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
78 Session::request_input_change_handling ()
80 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
81 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
87 Session::request_sync_source (Slave* new_slave)
89 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
92 seamless = Config->get_seamless_loop ();
94 if (dynamic_cast<Engine_Slave*>(new_slave)) {
95 /* JACK cannot support seamless looping at present */
96 Config->set_seamless_loop (false);
98 /* reset to whatever the value was before we last switched slaves */
99 Config->set_seamless_loop (_was_seamless);
102 /* save value of seamless from before the switch */
103 _was_seamless = seamless;
105 ev->slave = new_slave;
106 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
111 Session::request_transport_speed (double speed, bool as_default)
113 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
114 ev->third_yes_or_no = as_default; // as_default
115 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
119 /** Request a new transport speed, but if the speed parameter is exactly zero then use
120 * a very small +ve value to prevent the transport actually stopping. This method should
121 * be used by callers who are varying transport speed but don't ever want to stop it.
124 Session::request_transport_speed_nonzero (double speed, bool as_default)
130 request_transport_speed (speed, as_default);
134 Session::request_track_speed (Track* tr, double speed)
136 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
142 Session::request_stop (bool abort, bool clear_state)
144 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
145 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));
150 Session::request_locate (framepos_t target_frame, bool with_roll)
152 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
153 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
158 Session::force_locate (framepos_t target_frame, bool with_roll)
160 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
161 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
166 Session::unset_preroll_record_punch ()
168 if (_preroll_record_punch_pos >= 0) {
169 remove_event (_preroll_record_punch_pos, SessionEvent::RecordStart);
171 _preroll_record_punch_pos = -1;
175 Session::unset_preroll_record_trim ()
177 _preroll_record_trim_len = 0;
181 Session::request_preroll_record_punch (framepos_t rec_in, framecnt_t preroll)
183 if (actively_recording ()) {
186 unset_preroll_record_punch ();
187 unset_preroll_record_trim ();
188 framepos_t start = std::max ((framepos_t)0, rec_in - preroll);
190 _preroll_record_punch_pos = rec_in;
191 if (_preroll_record_punch_pos >= 0) {
192 replace_event (SessionEvent::RecordStart, _preroll_record_punch_pos);
193 config.set_punch_in (false);
194 config.set_punch_out (false);
196 maybe_enable_record ();
197 request_locate (start, true);
198 set_requested_return_frame (rec_in);
202 Session::request_preroll_record_trim (framepos_t rec_in, framecnt_t preroll)
204 if (actively_recording ()) {
207 unset_preroll_record_punch ();
208 unset_preroll_record_trim ();
210 config.set_punch_in (false);
211 config.set_punch_out (false);
213 framepos_t pos = std::max ((framepos_t)0, rec_in - preroll);
214 _preroll_record_trim_len = preroll;
215 maybe_enable_record ();
216 request_locate (pos, true);
217 set_requested_return_frame (rec_in);
221 Session::request_play_loop (bool yn, bool change_transport_roll)
224 // don't attempt to loop when not using Internal Transport
225 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
230 Location *location = _locations->auto_loop_location();
233 if (location == 0 && yn) {
234 error << _("Cannot loop - no loop range defined")
239 if (change_transport_roll) {
240 if (transport_rolling()) {
241 /* start looping at current speed */
242 target_speed = transport_speed ();
244 /* currently stopped */
246 /* start looping at normal speed */
253 /* leave the speed alone */
254 target_speed = transport_speed ();
257 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
258 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
262 if (!change_transport_roll) {
263 if (!transport_rolling()) {
264 /* we're not changing transport state, but we do want
265 to set up position for the new loop. Don't
266 do this if we're rolling already.
268 request_locate (location->start(), false);
272 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
273 // request an immediate locate to refresh the tracks
274 // after disabling looping
275 request_locate (_transport_frame-1, false);
281 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
283 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
285 ev->audio_range = *range;
287 ev->audio_range.clear ();
289 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
294 Session::request_cancel_play_range ()
296 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
302 Session::realtime_stop (bool abort, bool clear_state)
304 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
305 PostTransportWork todo = PostTransportWork (0);
307 /* assume that when we start, we'll be moving forwards */
309 if (_transport_speed < 0.0f) {
310 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
311 _default_transport_speed = 1.0;
313 todo = PostTransportWork (todo | PostTransportStop);
318 boost::shared_ptr<RouteList> r = routes.reader ();
320 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
321 (*i)->realtime_handle_transport_stopped ();
324 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
326 /* the duration change is not guaranteed to have happened, but is likely */
328 todo = PostTransportWork (todo | PostTransportDuration);
331 todo = PostTransportWork (todo | PostTransportAbort);
335 todo = PostTransportWork (todo | PostTransportClearSubstate);
339 add_post_transport_work (todo);
342 _clear_event_type (SessionEvent::StopOnce);
343 _clear_event_type (SessionEvent::RangeStop);
344 _clear_event_type (SessionEvent::RangeLocate);
346 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
347 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
349 if (clear_state && !Config->get_loop_is_mode()) {
353 reset_slave_state ();
355 _transport_speed = 0;
356 _target_transport_speed = 0;
358 g_atomic_int_set (&_playback_load, 100);
359 g_atomic_int_set (&_capture_load, 100);
361 if (config.get_use_video_sync()) {
362 waiting_for_sync_offset = true;
365 transport_sub_state = 0;
369 Session::realtime_locate ()
371 boost::shared_ptr<RouteList> r = routes.reader ();
372 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
373 (*i)->realtime_locate ();
378 Session::butler_transport_work ()
380 /* Note: this function executes in the butler thread context */
384 PostTransportWork ptw;
385 boost::shared_ptr<RouteList> r = routes.reader ();
388 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
390 ptw = post_transport_work();
392 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
395 if (ptw & PostTransportLocate) {
397 if (get_play_loop() && !Config->get_seamless_loop()) {
399 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
401 /* this locate might be happening while we are
404 * Non-seamless looping will require a locate (below) that
405 * will reset capture buffers and throw away data.
407 * Rather than first find all tracks and see if they
408 * have outstanding data, just do a flush anyway. It
409 * may be cheaper this way anyway, and is certainly
413 bool more_disk_io_to_do = false;
417 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
423 if (more_disk_io_to_do) {
432 if (ptw & PostTransportAdjustPlaybackBuffering) {
433 /* non_realtime_locate() calls Automatable::transport_located()
434 * for every route. This eventually calls
435 * ARDOUR::AutomationList::state () which has a LocaleGuard,
436 * and would switch locales forth/back every time.
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->adjust_playback_buffering ();
443 /* and refill those buffers ... */
445 (*i)->non_realtime_locate (_transport_frame);
450 if (ptw & PostTransportAdjustCaptureBuffering) {
451 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
452 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
454 tr->adjust_capture_buffering ();
459 if (ptw & PostTransportCurveRealloc) {
460 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
461 (*i)->curve_reallocate();
465 if (ptw & PostTransportInputChange) {
466 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
467 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
469 tr->non_realtime_input_change ();
474 if (ptw & PostTransportSpeed) {
475 non_realtime_set_speed ();
478 if (ptw & PostTransportReverse) {
481 cumulative_rf_motion = 0;
484 /* don't seek if locate will take care of that in non_realtime_stop() */
486 if (!(ptw & PostTransportLocate)) {
487 LocaleGuard lg; // see note for non_realtime_locate() above
488 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
489 (*i)->non_realtime_locate (_transport_frame);
491 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
492 /* new request, stop seeking, and start again */
493 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
500 if (ptw & PostTransportLocate) {
501 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
502 non_realtime_locate ();
505 if (ptw & PostTransportStop) {
506 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
508 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
513 if (ptw & PostTransportOverWrite) {
514 non_realtime_overwrite (on_entry, finished);
516 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
521 if (ptw & PostTransportAudition) {
522 non_realtime_set_audition ();
525 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
527 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
528 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
532 Session::non_realtime_set_speed ()
534 boost::shared_ptr<RouteList> rl = routes.reader();
535 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
536 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
538 tr->non_realtime_set_speed ();
544 Session::non_realtime_overwrite (int on_entry, bool& finished)
546 boost::shared_ptr<RouteList> rl = routes.reader();
547 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
548 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
549 if (tr && tr->pending_overwrite ()) {
550 tr->overwrite_existing_buffers ();
552 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
561 Session::non_realtime_locate ()
563 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
565 if (Config->get_loop_is_mode() && get_play_loop()) {
567 Location *loc = _locations->auto_loop_location();
569 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
570 /* jumped out of loop range: stop tracks from looping,
571 but leave loop (mode) enabled.
573 set_track_loop (false);
575 } else if (loc && Config->get_seamless_loop() &&
576 ((loc->start() <= _transport_frame) ||
577 (loc->end() > _transport_frame) ) ) {
579 /* jumping to start of loop. This might have been done before but it is
580 * idempotent and cheap. Doing it here ensures that when we start playback
581 * outside the loop we still flip tracks into the magic seamless mode
584 set_track_loop (true);
587 set_track_loop (false);
592 /* no more looping .. should have been noticed elsewhere */
597 LocaleGuard lg; // see note for non_realtime_locate() above
598 boost::shared_ptr<RouteList> rl = routes.reader();
599 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
600 (*i)->non_realtime_locate (_transport_frame);
604 _scene_changer->locate (_transport_frame);
606 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
607 rather than clearing them so that the RT thread has to spend time constructing
608 them (in Session::click).
613 #ifdef USE_TRACKS_CODE_FEATURES
615 Session::select_playhead_priority_target (framepos_t& jump_to)
619 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
625 if (Profile->get_trx() && transport_rolling() ) {
626 // We're playing, so do nothing.
627 // Next stop will put us where we need to be.
631 /* Note that the order of checking each AutoReturnTarget flag defines
632 the priority each flag.
634 Ardour/Mixbus: Last Locate
639 Tracks: Range Selection
645 if (autoreturn & RangeSelectionStart) {
646 if (!_range_selection.empty()) {
647 jump_to = _range_selection.from;
649 if (transport_rolling ()) {
650 /* Range selection no longer exists, but we're playing,
651 so do nothing. Next stop will put us where
659 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
660 /* don't try to handle loop play when synced to JACK */
662 if (!synced_to_engine()) {
663 Location *location = _locations->auto_loop_location();
666 jump_to = location->start();
668 if (Config->get_seamless_loop()) {
669 /* need to get track buffers reloaded */
670 set_track_loop (true);
676 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
677 if (!_object_selection.empty()) {
678 jump_to = _object_selection.from;
682 if (jump_to < 0 && (autoreturn & LastLocate)) {
683 jump_to = _last_roll_location;
691 Session::select_playhead_priority_target (framepos_t& jump_to)
693 if (config.get_external_sync() || !config.get_auto_return()) {
697 jump_to = _last_roll_location;
704 Session::follow_playhead_priority ()
708 if (select_playhead_priority_target (target)) {
709 request_locate (target);
714 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
720 PostTransportWork ptw = post_transport_work();
725 boost::shared_ptr<RouteList> rl = routes.reader();
726 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
727 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
728 if (tr && tr->get_captured_frames () != 0) {
734 /* stop and locate are merged here because they share a lot of common stuff */
737 now = localtime (&xnow);
740 auditioner->cancel_audition ();
743 cumulative_rf_motion = 0;
747 begin_reversible_command (Operations::capture);
748 _have_captured = true;
751 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
753 if (abort && did_record) {
754 /* no reason to save the session file when we remove sources
756 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
759 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
760 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
762 tr->transport_stopped_wallclock (*now, xnow, abort);
766 if (abort && did_record) {
767 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
770 boost::shared_ptr<RouteList> r = routes.reader ();
772 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
773 if (!(*i)->is_auditioner()) {
774 (*i)->set_pending_declick (0);
779 commit_reversible_command ();
780 /* increase take name */
781 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
782 string newname = config.get_take_name();
783 config.set_take_name(bump_name_number (newname));
787 if (_engine.running()) {
788 PostTransportWork ptw = post_transport_work ();
789 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
790 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
792 update_latency_compensation ();
795 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
797 if (auto_return_enabled ||
798 (ptw & PostTransportLocate) ||
799 (_requested_return_frame >= 0) ||
800 synced_to_engine()) {
802 if (pending_locate_flush) {
803 flush_all_inserts ();
806 // rg: what is the logic behind this case?
807 // _requested_return_frame should be ignored when synced_to_engine/slaved.
808 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
810 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
811 !(ptw & PostTransportLocate)) {
813 /* no explicit locate queued */
815 bool do_locate = false;
817 if (_requested_return_frame >= 0) {
819 /* explicit return request pre-queued in event list. overrides everything else */
821 _transport_frame = _requested_return_frame;
827 if (select_playhead_priority_target (jump_to)) {
829 _transport_frame = jump_to;
834 _transport_frame = _last_roll_location;
839 _requested_return_frame = -1;
842 _engine.transport_locate (_transport_frame);
849 unset_preroll_record_trim ();
851 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
854 if (ptw & PostTransportClearSubstate) {
856 if (!Config->get_loop_is_mode()) {
861 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
864 LocaleGuard lg; // see note for non_realtime_locate() above
865 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
866 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
867 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
868 (*i)->non_realtime_locate (_transport_frame);
870 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
872 /* we will be back */
880 /* don't bother with this stuff if we're disconnected from the engine,
881 because there will be no process callbacks to deliver stuff from
884 if (_engine.connected() && !_engine.freewheeling()) {
885 // need to queue this in the next RT cycle
886 _send_timecode_update = true;
888 if (!dynamic_cast<MTC_Slave*>(_slave)) {
889 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
891 /* This (::non_realtime_stop()) gets called by main
892 process thread, which will lead to confusion
893 when calling AsyncMIDIPort::write().
895 Something must be done. XXX
897 send_mmc_locate (_transport_frame);
901 if ((ptw & PostTransportLocate) && get_record_enabled()) {
902 /* This is scheduled by realtime_stop(), which is also done
903 * when a slave requests /locate/ for an initial sync.
904 * We can't hold up the slave for long with a save() here,
905 * without breaking its initial sync cycle.
907 * save state only if there's no slave or if it's not yet locked.
909 if (!_slave || !_slave->locked()) {
910 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
911 SaveSessionRequested (_current_snapshot_name);
916 /* always try to get rid of this */
918 remove_pending_capture_state ();
920 /* save the current state of things if appropriate */
922 if (did_record && !saved) {
923 SaveSessionRequested (_current_snapshot_name);
926 if (ptw & PostTransportStop) {
928 if (!Config->get_loop_is_mode()) {
933 PositionChanged (_transport_frame); /* EMIT SIGNAL */
934 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
935 TransportStateChange (); /* EMIT SIGNAL */
936 AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
938 /* and start it up again if relevant */
940 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
941 request_transport_speed (1.0);
944 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
945 around for next time.
947 pending_locate_roll = false;
951 Session::check_declick_out ()
953 bool locate_required = transport_sub_state & PendingLocate;
955 /* this is called after a process() iteration. if PendingDeclickOut was set,
956 it means that we were waiting to declick the output (which has just been
957 done) before maybe doing something else. this is where we do that "something else".
959 note: called from the audio thread.
962 if (transport_sub_state & PendingDeclickOut) {
964 if (locate_required) {
965 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
966 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
968 if (!(transport_sub_state & StopPendingCapture)) {
969 stop_transport (pending_abort);
970 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
974 } else if (transport_sub_state & PendingLoopDeclickOut) {
975 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
976 transport_sub_state &= ~PendingLoopDeclickOut;
981 Session::unset_play_loop ()
985 clear_events (SessionEvent::AutoLoop);
986 clear_events (SessionEvent::AutoLoopDeclick);
987 set_track_loop (false);
990 if (Config->get_seamless_loop()) {
991 /* likely need to flush track buffers: this will locate us to wherever we are */
992 add_post_transport_work (PostTransportLocate);
993 _butler->schedule_transport_work ();
999 Session::set_track_loop (bool yn)
1001 Location* loc = _locations->auto_loop_location ();
1007 boost::shared_ptr<RouteList> rl = routes.reader ();
1009 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1010 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1011 if (tr && !tr->hidden()) {
1012 tr->set_loop (yn ? loc : 0);
1018 Session::set_play_loop (bool yn, double speed)
1020 /* Called from event-handling context */
1024 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1025 /* nothing to do, or can't change loop status while recording */
1029 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1030 warning << string_compose (
1031 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1032 "Recommend changing the configured options"), PROGRAM_NAME)
1040 have_looped = false;
1044 unset_play_range ();
1046 if (Config->get_seamless_loop()) {
1047 if (!Config->get_loop_is_mode()) {
1048 /* set all tracks to use internal looping */
1049 set_track_loop (true);
1051 /* we will do this in the locate to the start OR when we hit the end
1052 * of the loop for the first time
1056 /* set all tracks to NOT use internal looping */
1057 set_track_loop (false);
1060 /* Put the delick and loop events in into the event list. The declick event will
1061 cause a de-clicking fade-out just before the end of the loop, and it will also result
1062 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1067 auto_loop_declick_range (loc, dcp, dcl);
1068 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1069 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1071 /* if requested to roll, locate to start of loop and
1072 * roll but ONLY if we're not already rolling.
1074 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1077 if (Config->get_loop_is_mode()) {
1078 /* loop IS a transport mode: if already
1079 rolling, do not locate to loop start.
1081 if (!transport_rolling() && (speed != 0.0)) {
1082 start_locate (loc->start(), true, true, false, true);
1086 start_locate (loc->start(), true, true, false, true);
1096 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1097 TransportStateChange ();
1100 Session::flush_all_inserts ()
1102 boost::shared_ptr<RouteList> r = routes.reader ();
1104 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1105 (*i)->flush_processors ();
1110 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1112 if (target_frame < 0) {
1113 error << _("Locate called for negative sample position - ignored") << endmsg;
1117 if (synced_to_engine()) {
1122 _slave->speed_and_position (sp, pos);
1124 if (target_frame != pos) {
1126 if (config.get_jack_time_master()) {
1127 /* actually locate now, since otherwise jack_timebase_callback
1128 will use the incorrect _transport_frame and report an old
1129 and incorrect time to Jack transport
1131 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1134 /* tell JACK to change transport position, and we will
1135 follow along later in ::follow_slave()
1138 _engine.transport_locate (target_frame);
1140 if (sp != 1.0f && with_roll) {
1141 _engine.transport_start ();
1147 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1152 Session::micro_locate (framecnt_t distance)
1154 boost::shared_ptr<RouteList> rl = routes.reader();
1155 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1156 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1157 if (tr && !tr->can_internal_playback_seek (distance)) {
1162 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1163 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1165 tr->internal_playback_seek (distance);
1169 _transport_frame += distance;
1173 /** @param with_mmc true to send a MMC locate command when the locate is done */
1175 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1177 bool need_butler = false;
1179 /* Locates for seamless looping are fairly different from other
1180 * locates. They assume that the diskstream buffers for each track
1181 * already have the correct data in them, and thus there is no need to
1182 * actually tell the tracks to locate. What does need to be done,
1183 * though, is all the housekeeping that is associated with non-linear
1184 * changes in the value of _transport_frame.
1187 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1188 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1190 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1192 /* already at the desired position. Not forced to locate,
1193 the loop isn't changing, so unless we're told to
1194 start rolling also, there's nothing to do but
1195 tell the world where we are (again).
1199 set_transport_speed (1.0, 0, false);
1201 loop_changing = false;
1202 Located (); /* EMIT SIGNAL */
1206 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1207 /* Schedule a declick. We'll be called again when its done.
1208 We only do it this way for ordinary locates, not those
1209 due to **seamless** loops.
1212 if (!(transport_sub_state & PendingDeclickOut)) {
1213 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1214 pending_locate_frame = target_frame;
1215 pending_locate_roll = with_roll;
1216 pending_locate_flush = with_flush;
1221 // Update Timecode time
1222 _transport_frame = target_frame;
1223 _last_roll_or_reversal_location = target_frame;
1224 timecode_time(_transport_frame, transmitting_timecode_time);
1226 /* do "stopped" stuff if:
1228 * we are rolling AND
1229 * no autoplay in effect AND
1230 * we're not going to keep rolling after the locate AND
1231 * !(playing a loop with JACK sync)
1235 bool transport_was_stopped = !transport_rolling();
1237 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1238 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1239 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1240 transport_was_stopped = true;
1242 /* otherwise tell the world that we located */
1246 if (force || !for_loop_enabled || loop_changing) {
1248 PostTransportWork todo = PostTransportLocate;
1250 if (with_roll && transport_was_stopped) {
1251 todo = PostTransportWork (todo | PostTransportRoll);
1254 add_post_transport_work (todo);
1259 /* this is functionally what clear_clicks() does but with a tentative lock */
1261 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1263 if (clickm.locked()) {
1265 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1274 /* switch from input if we're going to roll */
1275 if (Config->get_monitoring_model() == HardwareMonitoring) {
1276 set_track_monitor_input_status (!config.get_auto_input());
1279 /* otherwise we're going to stop, so do the opposite */
1280 if (Config->get_monitoring_model() == HardwareMonitoring) {
1281 set_track_monitor_input_status (true);
1285 /* cancel looped playback if transport pos outside of loop range */
1288 Location* al = _locations->auto_loop_location();
1291 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1293 // located outside the loop: cancel looping directly, this is called from event handling context
1295 have_looped = false;
1297 if (!Config->get_loop_is_mode()) {
1298 set_play_loop (false, _transport_speed);
1300 if (Config->get_seamless_loop()) {
1301 /* this will make the non_realtime_locate() in the butler
1302 which then causes seek() in tracks actually do the right
1305 set_track_loop (false);
1309 } else if (_transport_frame == al->start()) {
1311 // located to start of loop - this is looping, basically
1315 if (_last_roll_location != al->start()) {
1316 /* didn't start at loop start - playback must have
1317 * started before loop since we've now hit the loop
1320 add_post_transport_work (PostTransportLocate);
1326 boost::shared_ptr<RouteList> rl = routes.reader();
1328 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1329 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1331 if (tr && tr->rec_enable_control()->get_value()) {
1332 // tell it we've looped, so it can deal with the record state
1333 tr->transport_looped (_transport_frame);
1338 TransportLooped(); // EMIT SIGNAL
1344 _butler->schedule_transport_work ();
1347 loop_changing = false;
1349 _send_timecode_update = true;
1352 send_mmc_locate (_transport_frame);
1355 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1356 Located (); /* EMIT SIGNAL */
1359 /** Set the transport speed.
1360 * Called from the process thread.
1361 * @param speed New speed
1364 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1366 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1367 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1369 if (_transport_speed == speed) {
1370 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1371 _default_transport_speed = 1.0;
1376 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1377 /* no varispeed during recording */
1378 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1379 _transport_speed, _transport_frame));
1383 _target_transport_speed = fabs(speed);
1385 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1386 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1390 speed = min (8.0, speed);
1391 } else if (speed < 0) {
1392 speed = max (-8.0, speed);
1395 if (transport_rolling() && speed == 0.0) {
1397 /* we are rolling and we want to stop */
1399 if (Config->get_monitoring_model() == HardwareMonitoring) {
1400 set_track_monitor_input_status (true);
1403 if (synced_to_engine ()) {
1405 /* do this here because our response to the slave won't
1408 _play_range = false;
1411 _engine.transport_stop ();
1413 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1415 if (!auto_return_enabled) {
1416 _requested_return_frame = destination_frame;
1419 stop_transport (abort);
1422 } else if (transport_stopped() && speed == 1.0) {
1424 _default_transport_speed = speed;
1426 /* we are stopped and we want to start rolling at speed 1 */
1428 if (Config->get_loop_is_mode() && play_loop) {
1430 Location *location = _locations->auto_loop_location();
1432 if (location != 0) {
1433 if (_transport_frame != location->start()) {
1435 if (Config->get_seamless_loop()) {
1436 /* force tracks to do their thing */
1437 set_track_loop (true);
1440 /* jump to start and then roll from there */
1442 request_locate (location->start(), true);
1448 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1449 set_track_monitor_input_status (false);
1452 if (synced_to_engine()) {
1453 _engine.transport_start ();
1460 /* not zero, not 1.0 ... varispeed */
1462 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1463 warning << string_compose (
1464 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1470 if (actively_recording()) {
1474 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1478 if (speed < 0.0 && _transport_frame == 0) {
1484 /* if we are reversing relative to the current speed, or relative to the speed
1485 before the last stop, then we have to do extra work.
1488 PostTransportWork todo = PostTransportWork (0);
1490 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1491 todo = PostTransportWork (todo | PostTransportReverse);
1492 _last_roll_or_reversal_location = _transport_frame;
1495 _last_transport_speed = _transport_speed;
1496 _transport_speed = speed;
1499 _default_transport_speed = speed;
1502 boost::shared_ptr<RouteList> rl = routes.reader();
1503 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1504 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1505 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1506 todo = PostTransportWork (todo | PostTransportSpeed);
1511 add_post_transport_work (todo);
1512 _butler->schedule_transport_work ();
1515 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1517 /* throttle signal emissions.
1518 * when slaved [_last]_transport_speed
1519 * usually changes every cycle (tiny amounts due to DLL).
1520 * Emitting a signal every cycle is overkill and unwarranted.
1522 * Using _last_transport_speed is not acceptable,
1523 * since it allows for large changes over a long period
1524 * of time. Hence we introduce a dedicated variable to keep track
1526 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1527 * for TransportStateChange() here is the ShuttleControl display.
1529 if (fabs (_signalled_varispeed - speed) > .002
1530 // still, signal hard changes to 1.0 and 0.0:
1531 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1532 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1535 TransportStateChange (); /* EMIT SIGNAL */
1536 _signalled_varispeed = speed;
1542 /** Stop the transport. */
1544 Session::stop_transport (bool abort, bool clear_state)
1546 if (_transport_speed == 0.0f) {
1550 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1552 if (!get_transport_declick_required()) {
1554 /* stop has not yet been scheduled */
1556 boost::shared_ptr<RouteList> rl = routes.reader();
1557 framepos_t stop_target = audible_frame();
1559 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1560 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1562 tr->prepare_to_stop (_transport_frame, stop_target);
1568 if (actively_recording() && /* we are recording */
1569 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1571 /* we need to capture the audio that is still somewhere in the pipeline between
1572 wherever it was generated and the process callback. This means that even though
1573 the user (or something else) has asked us to stop, we have to roll
1574 past this point and then reset the playhead/transport location to
1575 the position at which the stop was requested.
1577 we still need playback to "stop" now, however, which is why we schedule
1581 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1582 _transport_frame, _worst_input_latency,
1583 _transport_frame + _worst_input_latency,
1586 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1587 _transport_frame + _worst_input_latency,
1592 /* request a declick at the start of the next process cycle() so that playback ceases.
1593 It will remain silent until we actually stop (at the StopOnce event somewhere in
1594 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1595 does not stop the transport too early.
1597 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1601 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1603 new_bits = PendingDeclickOut;
1604 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1607 /* we'll be called again after the declick */
1608 transport_sub_state = SubState (transport_sub_state|new_bits);
1609 pending_abort = abort;
1615 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1617 /* declick was scheduled, but we've been called again, which means it is really time to stop
1619 XXX: we should probably split this off into its own method and call it explicitly.
1622 realtime_stop (abort, clear_state);
1623 _butler->schedule_transport_work ();
1627 /** Called from the process thread */
1629 Session::start_transport ()
1631 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1633 _last_roll_location = _transport_frame;
1634 _last_roll_or_reversal_location = _transport_frame;
1636 have_looped = false;
1638 /* if record status is Enabled, move it to Recording. if its
1639 already Recording, move it to Disabled.
1642 switch (record_status()) {
1644 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1651 disable_record (false);
1659 transport_sub_state |= PendingDeclickIn;
1661 _transport_speed = _default_transport_speed;
1662 _target_transport_speed = _transport_speed;
1664 boost::shared_ptr<RouteList> rl = routes.reader();
1665 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1666 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1668 tr->realtime_set_speed (tr->speed(), true);
1672 if (!_engine.freewheeling()) {
1673 Timecode::Time time;
1674 timecode_time_subframes (_transport_frame, time);
1675 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1676 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1679 if (actively_recording() && click_data && config.get_count_in ()) {
1680 /* calculate count-in duration (in audio samples)
1681 * - use [fixed] tempo/meter at _transport_frame
1682 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1684 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1685 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1687 double div = meter.divisions_per_bar ();
1688 double pulses = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * div / 4.0;
1689 double beats_left = fmod (pulses, div);
1691 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1693 double dt = _count_in_samples / div;
1694 if (beats_left == 0) {
1695 /* at bar boundary, count-in 2 bars before start. */
1696 _count_in_samples *= 2;
1698 /* beats left after full bar until roll position */
1699 _count_in_samples += meter.frames_per_grid (tempo, _current_frame_rate) * beats_left;
1703 framepos_t cf = _transport_frame - _count_in_samples;
1704 while (cf < _transport_frame) {
1705 add_click (cf - _worst_track_latency, clickbeat == 0);
1707 clickbeat = fmod (clickbeat + 1, div);
1712 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1713 TransportStateChange (); /* EMIT SIGNAL */
1716 /** Do any transport work in the audio thread that needs to be done after the
1717 * transport thread is finished. Audio thread, realtime safe.
1720 Session::post_transport ()
1722 PostTransportWork ptw = post_transport_work ();
1724 if (ptw & PostTransportAudition) {
1725 if (auditioner && auditioner->auditioning()) {
1726 process_function = &Session::process_audition;
1728 process_function = &Session::process_with_events;
1732 if (ptw & PostTransportStop) {
1734 transport_sub_state = 0;
1737 if (ptw & PostTransportLocate) {
1739 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1742 transport_sub_state = 0;
1747 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1750 set_post_transport_work (PostTransportWork (0));
1754 Session::reset_rf_scale (framecnt_t motion)
1756 cumulative_rf_motion += motion;
1758 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1760 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1762 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1774 Session::mtc_status_changed (bool yn)
1776 g_atomic_int_set (&_mtc_active, yn);
1777 MTCSyncStateChanged( yn );
1781 Session::ltc_status_changed (bool yn)
1783 g_atomic_int_set (&_ltc_active, yn);
1784 LTCSyncStateChanged( yn );
1788 Session::use_sync_source (Slave* new_slave)
1790 /* Runs in process() context */
1792 bool non_rt_required = false;
1794 /* XXX this deletion is problematic because we're in RT context */
1799 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1801 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1802 MTCSyncStateChanged(mtc_slave->locked() );
1804 if (g_atomic_int_get (&_mtc_active) ){
1805 g_atomic_int_set (&_mtc_active, 0);
1806 MTCSyncStateChanged( false );
1808 mtc_status_connection.disconnect ();
1811 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1813 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1814 LTCSyncStateChanged (ltc_slave->locked() );
1816 if (g_atomic_int_get (&_ltc_active) ){
1817 g_atomic_int_set (&_ltc_active, 0);
1818 LTCSyncStateChanged( false );
1820 ltc_status_connection.disconnect ();
1823 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1825 // need to queue this for next process() cycle
1826 _send_timecode_update = true;
1828 boost::shared_ptr<RouteList> rl = routes.reader();
1829 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1830 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1831 if (tr && !tr->hidden()) {
1832 if (tr->realtime_set_speed (tr->speed(), true)) {
1833 non_rt_required = true;
1835 tr->set_slaved (_slave != 0);
1839 if (non_rt_required) {
1840 add_post_transport_work (PostTransportSpeed);
1841 _butler->schedule_transport_work ();
1848 Session::drop_sync_source ()
1850 request_sync_source (0);
1854 Session::switch_to_sync_source (SyncSource src)
1858 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1862 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1867 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1870 catch (failed_constructor& err) {
1876 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1881 new_slave = new LTC_Slave (*this);
1884 catch (failed_constructor& err) {
1891 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1896 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1899 catch (failed_constructor& err) {
1905 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1909 if (config.get_video_pullup() != 0.0f) {
1913 new_slave = new Engine_Slave (*AudioEngine::instance());
1921 request_sync_source (new_slave);
1925 Session::set_track_speed (Track* track, double speed)
1927 if (track->realtime_set_speed (speed, false)) {
1928 add_post_transport_work (PostTransportSpeed);
1929 _butler->schedule_transport_work ();
1935 Session::unset_play_range ()
1937 _play_range = false;
1938 _clear_event_type (SessionEvent::RangeStop);
1939 _clear_event_type (SessionEvent::RangeLocate);
1943 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1947 /* Called from event-processing context */
1949 unset_play_range ();
1951 if (range.empty()) {
1952 /* _play_range set to false in unset_play_range()
1954 if (!leave_rolling) {
1955 /* stop transport */
1956 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1964 /* cancel loop play */
1967 list<AudioRange>::size_type sz = range.size();
1971 list<AudioRange>::iterator i = range.begin();
1972 list<AudioRange>::iterator next;
1974 while (i != range.end()) {
1979 /* locating/stopping is subject to delays for declicking.
1982 framepos_t requested_frame = i->end;
1984 if (requested_frame > current_block_size) {
1985 requested_frame -= current_block_size;
1987 requested_frame = 0;
1990 if (next == range.end()) {
1991 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1993 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2001 } else if (sz == 1) {
2003 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2008 /* save range so we can do auto-return etc. */
2010 current_audio_range = range;
2012 /* now start rolling at the right place */
2014 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2017 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2018 TransportStateChange ();
2022 Session::request_bounded_roll (framepos_t start, framepos_t end)
2024 AudioRange ar (start, end, 0);
2025 list<AudioRange> lar;
2028 request_play_range (&lar, true);
2032 Session::set_requested_return_frame (framepos_t return_to)
2034 _requested_return_frame = return_to;
2038 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2040 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2041 ev->target2_frame = start;
2046 Session::engine_halted ()
2050 /* there will be no more calls to process(), so
2051 we'd better clean up for ourselves, right now.
2053 but first, make sure the butler is out of
2061 realtime_stop (false, true);
2062 non_realtime_stop (false, 0, ignored);
2063 transport_sub_state = 0;
2065 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2066 TransportStateChange (); /* EMIT SIGNAL */
2071 Session::xrun_recovery ()
2075 Xrun (_transport_frame); /* EMIT SIGNAL */
2077 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2079 /* it didn't actually halt, but we need
2080 to handle things in the same way.
2088 Session::route_processors_changed (RouteProcessorChange c)
2090 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2094 if (c.type == RouteProcessorChange::MeterPointChange) {
2099 if (c.type == RouteProcessorChange::RealTimeChange) {
2104 update_latency_compensation ();
2111 Session::allow_auto_play (bool yn)
2113 auto_play_legal = yn;
2117 Session::maybe_stop (framepos_t limit)
2119 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2120 if (synced_to_engine () && config.get_jack_time_master ()) {
2121 _engine.transport_stop ();
2122 } else if (!synced_to_engine ()) {
2131 Session::send_mmc_locate (framepos_t t)
2137 if (!_engine.freewheeling()) {
2138 Timecode::Time time;
2139 timecode_time_subframes (t, time);
2140 send_immediate_mmc (MIDI::MachineControlCommand (time));
2144 /** Ask the transport to not send timecode until further notice. The suspension
2145 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2146 * should be checked by the caller to find out when.
2149 Session::request_suspend_timecode_transmission ()
2151 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2156 Session::request_resume_timecode_transmission ()
2158 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2163 Session::timecode_transmission_suspended () const
2165 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;