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"
51 #include "ardour/vca.h"
52 #include "ardour/vca_manager.h"
57 using namespace ARDOUR;
61 Session::add_post_transport_work (PostTransportWork ptw)
63 PostTransportWork oldval;
64 PostTransportWork newval;
68 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
69 newval = PostTransportWork (oldval | ptw);
70 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
76 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
80 Session::request_input_change_handling ()
82 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
83 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
89 Session::request_sync_source (Slave* new_slave)
91 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
94 seamless = Config->get_seamless_loop ();
96 if (dynamic_cast<Engine_Slave*>(new_slave)) {
97 /* JACK cannot support seamless looping at present */
98 Config->set_seamless_loop (false);
100 /* reset to whatever the value was before we last switched slaves */
101 Config->set_seamless_loop (_was_seamless);
104 /* save value of seamless from before the switch */
105 _was_seamless = seamless;
107 ev->slave = new_slave;
108 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
113 Session::request_transport_speed (double speed, bool as_default)
115 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
116 ev->third_yes_or_no = as_default; // as_default
117 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
121 /** Request a new transport speed, but if the speed parameter is exactly zero then use
122 * a very small +ve value to prevent the transport actually stopping. This method should
123 * be used by callers who are varying transport speed but don't ever want to stop it.
126 Session::request_transport_speed_nonzero (double speed, bool as_default)
132 request_transport_speed (speed, as_default);
136 Session::request_track_speed (Track* tr, double speed)
138 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
144 Session::request_stop (bool abort, bool clear_state)
146 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
147 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));
152 Session::request_locate (framepos_t target_frame, bool with_roll)
154 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
155 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
160 Session::force_locate (framepos_t target_frame, bool with_roll)
162 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
163 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
168 Session::unset_preroll_record_punch ()
170 if (_preroll_record_punch_pos >= 0) {
171 remove_event (_preroll_record_punch_pos, SessionEvent::RecordStart);
173 _preroll_record_punch_pos = -1;
177 Session::unset_preroll_record_trim ()
179 _preroll_record_trim_len = 0;
183 Session::request_preroll_record_punch (framepos_t rec_in, framecnt_t preroll)
185 if (actively_recording ()) {
188 unset_preroll_record_punch ();
189 unset_preroll_record_trim ();
190 framepos_t start = std::max ((framepos_t)0, rec_in - preroll);
192 _preroll_record_punch_pos = rec_in;
193 if (_preroll_record_punch_pos >= 0) {
194 replace_event (SessionEvent::RecordStart, _preroll_record_punch_pos);
195 config.set_punch_in (false);
196 config.set_punch_out (false);
198 maybe_enable_record ();
199 request_locate (start, true);
200 set_requested_return_frame (rec_in);
204 Session::request_preroll_record_trim (framepos_t rec_in, framecnt_t preroll)
206 if (actively_recording ()) {
209 unset_preroll_record_punch ();
210 unset_preroll_record_trim ();
212 config.set_punch_in (false);
213 config.set_punch_out (false);
215 framepos_t pos = std::max ((framepos_t)0, rec_in - preroll);
216 _preroll_record_trim_len = preroll;
217 maybe_enable_record ();
218 request_locate (pos, true);
219 set_requested_return_frame (rec_in);
223 Session::request_count_in_record ()
225 if (actively_recording ()) {
228 if (transport_rolling()) {
231 maybe_enable_record ();
232 _count_in_once = true;
233 request_transport_speed (1.0, true);
237 Session::request_play_loop (bool yn, bool change_transport_roll)
240 // don't attempt to loop when not using Internal Transport
241 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
246 Location *location = _locations->auto_loop_location();
249 if (location == 0 && yn) {
250 error << _("Cannot loop - no loop range defined")
255 if (change_transport_roll) {
256 if (transport_rolling()) {
257 /* start looping at current speed */
258 target_speed = transport_speed ();
260 /* currently stopped */
262 /* start looping at normal speed */
269 /* leave the speed alone */
270 target_speed = transport_speed ();
273 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
274 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
278 if (!change_transport_roll) {
279 if (!transport_rolling()) {
280 /* we're not changing transport state, but we do want
281 to set up position for the new loop. Don't
282 do this if we're rolling already.
284 request_locate (location->start(), false);
288 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
289 // request an immediate locate to refresh the tracks
290 // after disabling looping
291 request_locate (_transport_frame-1, false);
297 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
299 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
301 ev->audio_range = *range;
303 ev->audio_range.clear ();
305 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
310 Session::request_cancel_play_range ()
312 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
318 Session::realtime_stop (bool abort, bool clear_state)
320 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
321 PostTransportWork todo = PostTransportWork (0);
323 /* assume that when we start, we'll be moving forwards */
325 if (_transport_speed < 0.0f) {
326 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
327 _default_transport_speed = 1.0;
329 todo = PostTransportWork (todo | PostTransportStop);
334 boost::shared_ptr<RouteList> r = routes.reader ();
336 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
337 (*i)->realtime_handle_transport_stopped ();
340 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
342 /* the duration change is not guaranteed to have happened, but is likely */
344 todo = PostTransportWork (todo | PostTransportDuration);
347 todo = PostTransportWork (todo | PostTransportAbort);
351 todo = PostTransportWork (todo | PostTransportClearSubstate);
355 add_post_transport_work (todo);
358 _clear_event_type (SessionEvent::StopOnce);
359 _clear_event_type (SessionEvent::RangeStop);
360 _clear_event_type (SessionEvent::RangeLocate);
362 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
363 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
365 if (clear_state && !Config->get_loop_is_mode()) {
369 reset_slave_state ();
371 _transport_speed = 0;
372 _target_transport_speed = 0;
374 g_atomic_int_set (&_playback_load, 100);
375 g_atomic_int_set (&_capture_load, 100);
377 if (config.get_use_video_sync()) {
378 waiting_for_sync_offset = true;
381 transport_sub_state = 0;
385 Session::realtime_locate ()
387 boost::shared_ptr<RouteList> r = routes.reader ();
388 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
389 (*i)->realtime_locate ();
394 Session::butler_transport_work ()
396 /* Note: this function executes in the butler thread context */
400 PostTransportWork ptw;
401 boost::shared_ptr<RouteList> r = routes.reader ();
404 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
406 ptw = post_transport_work();
408 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
411 if (ptw & PostTransportLocate) {
413 if (get_play_loop() && !Config->get_seamless_loop()) {
415 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
417 /* this locate might be happening while we are
420 * Non-seamless looping will require a locate (below) that
421 * will reset capture buffers and throw away data.
423 * Rather than first find all tracks and see if they
424 * have outstanding data, just do a flush anyway. It
425 * may be cheaper this way anyway, and is certainly
429 bool more_disk_io_to_do = false;
433 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
439 if (more_disk_io_to_do) {
448 if (ptw & PostTransportAdjustPlaybackBuffering) {
449 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
450 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
452 tr->adjust_playback_buffering ();
453 /* and refill those buffers ... */
455 (*i)->non_realtime_locate (_transport_frame);
457 VCAList v = _vca_manager->vcas ();
458 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
459 (*i)->transport_located (_transport_frame);
463 if (ptw & PostTransportAdjustCaptureBuffering) {
464 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
465 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
467 tr->adjust_capture_buffering ();
472 if (ptw & PostTransportCurveRealloc) {
473 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
474 (*i)->curve_reallocate();
478 if (ptw & PostTransportInputChange) {
479 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
480 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
482 tr->non_realtime_input_change ();
487 if (ptw & PostTransportSpeed) {
488 non_realtime_set_speed ();
491 if (ptw & PostTransportReverse) {
494 cumulative_rf_motion = 0;
497 /* don't seek if locate will take care of that in non_realtime_stop() */
499 if (!(ptw & PostTransportLocate)) {
500 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
501 (*i)->non_realtime_locate (_transport_frame);
503 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
504 /* new request, stop seeking, and start again */
505 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
509 VCAList v = _vca_manager->vcas ();
510 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
511 (*i)->transport_located (_transport_frame);
516 if (ptw & PostTransportLocate) {
517 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
518 non_realtime_locate ();
521 if (ptw & PostTransportStop) {
522 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
524 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
529 if (ptw & PostTransportOverWrite) {
530 non_realtime_overwrite (on_entry, finished);
532 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
537 if (ptw & PostTransportAudition) {
538 non_realtime_set_audition ();
541 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
543 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
544 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
548 Session::non_realtime_set_speed ()
550 boost::shared_ptr<RouteList> rl = routes.reader();
551 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
552 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
554 tr->non_realtime_set_speed ();
560 Session::non_realtime_overwrite (int on_entry, bool& finished)
562 boost::shared_ptr<RouteList> rl = routes.reader();
563 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
564 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
565 if (tr && tr->pending_overwrite ()) {
566 tr->overwrite_existing_buffers ();
568 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
577 Session::non_realtime_locate ()
579 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
581 if (Config->get_loop_is_mode() && get_play_loop()) {
583 Location *loc = _locations->auto_loop_location();
585 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
586 /* jumped out of loop range: stop tracks from looping,
587 but leave loop (mode) enabled.
589 set_track_loop (false);
591 } else if (loc && Config->get_seamless_loop() &&
592 ((loc->start() <= _transport_frame) ||
593 (loc->end() > _transport_frame) ) ) {
595 /* jumping to start of loop. This might have been done before but it is
596 * idempotent and cheap. Doing it here ensures that when we start playback
597 * outside the loop we still flip tracks into the magic seamless mode
600 set_track_loop (true);
603 set_track_loop (false);
608 /* no more looping .. should have been noticed elsewhere */
613 boost::shared_ptr<RouteList> rl = routes.reader();
614 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
615 (*i)->non_realtime_locate (_transport_frame);
619 VCAList v = _vca_manager->vcas ();
620 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
621 (*i)->transport_located (_transport_frame);
625 _scene_changer->locate (_transport_frame);
627 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
628 rather than clearing them so that the RT thread has to spend time constructing
629 them (in Session::click).
634 #ifdef USE_TRACKS_CODE_FEATURES
636 Session::select_playhead_priority_target (framepos_t& jump_to)
640 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
646 if (Profile->get_trx() && transport_rolling() ) {
647 // We're playing, so do nothing.
648 // Next stop will put us where we need to be.
652 /* Note that the order of checking each AutoReturnTarget flag defines
653 the priority each flag.
655 Ardour/Mixbus: Last Locate
660 Tracks: Range Selection
666 if (autoreturn & RangeSelectionStart) {
667 if (!_range_selection.empty()) {
668 jump_to = _range_selection.from;
670 if (transport_rolling ()) {
671 /* Range selection no longer exists, but we're playing,
672 so do nothing. Next stop will put us where
680 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
681 /* don't try to handle loop play when synced to JACK */
683 if (!synced_to_engine()) {
684 Location *location = _locations->auto_loop_location();
687 jump_to = location->start();
689 if (Config->get_seamless_loop()) {
690 /* need to get track buffers reloaded */
691 set_track_loop (true);
697 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
698 if (!_object_selection.empty()) {
699 jump_to = _object_selection.from;
703 if (jump_to < 0 && (autoreturn & LastLocate)) {
704 jump_to = _last_roll_location;
712 Session::select_playhead_priority_target (framepos_t& jump_to)
714 if (config.get_external_sync() || !config.get_auto_return()) {
718 jump_to = _last_roll_location;
725 Session::follow_playhead_priority ()
729 if (select_playhead_priority_target (target)) {
730 request_locate (target);
735 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
741 PostTransportWork ptw = post_transport_work();
746 boost::shared_ptr<RouteList> rl = routes.reader();
747 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
748 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
749 if (tr && tr->get_captured_frames () != 0) {
755 /* stop and locate are merged here because they share a lot of common stuff */
758 now = localtime (&xnow);
761 auditioner->cancel_audition ();
764 cumulative_rf_motion = 0;
768 begin_reversible_command (Operations::capture);
769 _have_captured = true;
772 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
774 if (abort && did_record) {
775 /* no reason to save the session file when we remove sources
777 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
780 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
781 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
783 tr->transport_stopped_wallclock (*now, xnow, abort);
787 if (abort && did_record) {
788 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
791 boost::shared_ptr<RouteList> r = routes.reader ();
793 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
794 if (!(*i)->is_auditioner()) {
795 (*i)->set_pending_declick (0);
800 commit_reversible_command ();
801 /* increase take name */
802 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
803 string newname = config.get_take_name();
804 config.set_take_name(bump_name_number (newname));
808 if (_engine.running()) {
809 PostTransportWork ptw = post_transport_work ();
811 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
812 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
814 VCAList v = _vca_manager->vcas ();
815 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
816 (*i)->transport_stopped (_transport_frame);
819 update_latency_compensation ();
822 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
824 if (auto_return_enabled ||
825 (ptw & PostTransportLocate) ||
826 (_requested_return_frame >= 0) ||
827 synced_to_engine()) {
829 if (pending_locate_flush) {
830 flush_all_inserts ();
833 // rg: what is the logic behind this case?
834 // _requested_return_frame should be ignored when synced_to_engine/slaved.
835 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
837 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
838 !(ptw & PostTransportLocate)) {
840 /* no explicit locate queued */
842 bool do_locate = false;
844 if (_requested_return_frame >= 0) {
846 /* explicit return request pre-queued in event list. overrides everything else */
848 _transport_frame = _requested_return_frame;
854 if (select_playhead_priority_target (jump_to)) {
856 _transport_frame = jump_to;
861 _transport_frame = _last_roll_location;
866 _requested_return_frame = -1;
869 _engine.transport_locate (_transport_frame);
876 unset_preroll_record_trim ();
878 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
881 if (ptw & PostTransportClearSubstate) {
883 if (!Config->get_loop_is_mode()) {
888 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
891 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
892 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
893 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
894 (*i)->non_realtime_locate (_transport_frame);
896 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
898 /* we will be back */
905 VCAList v = _vca_manager->vcas ();
906 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
907 (*i)->transport_located (_transport_frame);
913 /* don't bother with this stuff if we're disconnected from the engine,
914 because there will be no process callbacks to deliver stuff from
917 if (_engine.connected() && !_engine.freewheeling()) {
918 // need to queue this in the next RT cycle
919 _send_timecode_update = true;
921 if (!dynamic_cast<MTC_Slave*>(_slave)) {
922 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
924 /* This (::non_realtime_stop()) gets called by main
925 process thread, which will lead to confusion
926 when calling AsyncMIDIPort::write().
928 Something must be done. XXX
930 send_mmc_locate (_transport_frame);
934 if ((ptw & PostTransportLocate) && get_record_enabled()) {
935 /* This is scheduled by realtime_stop(), which is also done
936 * when a slave requests /locate/ for an initial sync.
937 * We can't hold up the slave for long with a save() here,
938 * without breaking its initial sync cycle.
940 * save state only if there's no slave or if it's not yet locked.
942 if (!_slave || !_slave->locked()) {
943 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
944 SaveSessionRequested (_current_snapshot_name);
949 /* always try to get rid of this */
951 remove_pending_capture_state ();
953 /* save the current state of things if appropriate */
955 if (did_record && !saved) {
956 SaveSessionRequested (_current_snapshot_name);
959 if (ptw & PostTransportStop) {
961 if (!Config->get_loop_is_mode()) {
966 PositionChanged (_transport_frame); /* EMIT SIGNAL */
967 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
968 TransportStateChange (); /* EMIT SIGNAL */
969 AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
971 /* and start it up again if relevant */
973 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
974 request_transport_speed (1.0);
977 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
978 around for next time.
980 pending_locate_roll = false;
984 Session::check_declick_out ()
986 bool locate_required = transport_sub_state & PendingLocate;
988 /* this is called after a process() iteration. if PendingDeclickOut was set,
989 it means that we were waiting to declick the output (which has just been
990 done) before maybe doing something else. this is where we do that "something else".
992 note: called from the audio thread.
995 if (transport_sub_state & PendingDeclickOut) {
997 if (locate_required) {
998 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
999 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1001 if (!(transport_sub_state & StopPendingCapture)) {
1002 stop_transport (pending_abort);
1003 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1007 } else if (transport_sub_state & PendingLoopDeclickOut) {
1008 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
1009 transport_sub_state &= ~PendingLoopDeclickOut;
1014 Session::unset_play_loop ()
1018 clear_events (SessionEvent::AutoLoop);
1019 clear_events (SessionEvent::AutoLoopDeclick);
1020 set_track_loop (false);
1023 if (Config->get_seamless_loop()) {
1024 /* likely need to flush track buffers: this will locate us to wherever we are */
1025 add_post_transport_work (PostTransportLocate);
1026 _butler->schedule_transport_work ();
1032 Session::set_track_loop (bool yn)
1034 Location* loc = _locations->auto_loop_location ();
1040 boost::shared_ptr<RouteList> rl = routes.reader ();
1042 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1043 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1044 if (tr && !tr->hidden()) {
1045 tr->set_loop (yn ? loc : 0);
1051 Session::set_play_loop (bool yn, double speed)
1053 /* Called from event-handling context */
1057 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1058 /* nothing to do, or can't change loop status while recording */
1062 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1063 warning << string_compose (
1064 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1065 "Recommend changing the configured options"), PROGRAM_NAME)
1073 have_looped = false;
1077 unset_play_range ();
1079 if (Config->get_seamless_loop()) {
1080 if (!Config->get_loop_is_mode()) {
1081 /* set all tracks to use internal looping */
1082 set_track_loop (true);
1084 /* we will do this in the locate to the start OR when we hit the end
1085 * of the loop for the first time
1089 /* set all tracks to NOT use internal looping */
1090 set_track_loop (false);
1093 /* Put the delick and loop events in into the event list. The declick event will
1094 cause a de-clicking fade-out just before the end of the loop, and it will also result
1095 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1100 auto_loop_declick_range (loc, dcp, dcl);
1101 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1102 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1104 /* if requested to roll, locate to start of loop and
1105 * roll but ONLY if we're not already rolling.
1107 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1110 if (Config->get_loop_is_mode()) {
1111 /* loop IS a transport mode: if already
1112 rolling, do not locate to loop start.
1114 if (!transport_rolling() && (speed != 0.0)) {
1115 start_locate (loc->start(), true, true, false, true);
1119 start_locate (loc->start(), true, true, false, true);
1129 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1130 TransportStateChange ();
1133 Session::flush_all_inserts ()
1135 boost::shared_ptr<RouteList> r = routes.reader ();
1137 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1138 (*i)->flush_processors ();
1143 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1145 if (target_frame < 0) {
1146 error << _("Locate called for negative sample position - ignored") << endmsg;
1150 if (synced_to_engine()) {
1155 _slave->speed_and_position (sp, pos);
1157 if (target_frame != pos) {
1159 if (config.get_jack_time_master()) {
1160 /* actually locate now, since otherwise jack_timebase_callback
1161 will use the incorrect _transport_frame and report an old
1162 and incorrect time to Jack transport
1164 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1167 /* tell JACK to change transport position, and we will
1168 follow along later in ::follow_slave()
1171 _engine.transport_locate (target_frame);
1173 if (sp != 1.0f && with_roll) {
1174 _engine.transport_start ();
1180 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1185 Session::micro_locate (framecnt_t distance)
1187 boost::shared_ptr<RouteList> rl = routes.reader();
1188 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1189 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1190 if (tr && !tr->can_internal_playback_seek (distance)) {
1195 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1196 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1198 tr->internal_playback_seek (distance);
1202 _transport_frame += distance;
1206 /** @param with_mmc true to send a MMC locate command when the locate is done */
1208 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1210 bool need_butler = false;
1212 /* Locates for seamless looping are fairly different from other
1213 * locates. They assume that the diskstream buffers for each track
1214 * already have the correct data in them, and thus there is no need to
1215 * actually tell the tracks to locate. What does need to be done,
1216 * though, is all the housekeeping that is associated with non-linear
1217 * changes in the value of _transport_frame.
1220 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1221 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1223 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1225 /* already at the desired position. Not forced to locate,
1226 the loop isn't changing, so unless we're told to
1227 start rolling also, there's nothing to do but
1228 tell the world where we are (again).
1232 set_transport_speed (1.0, 0, false);
1234 loop_changing = false;
1235 Located (); /* EMIT SIGNAL */
1239 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1240 /* Schedule a declick. We'll be called again when its done.
1241 We only do it this way for ordinary locates, not those
1242 due to **seamless** loops.
1245 if (!(transport_sub_state & PendingDeclickOut)) {
1246 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1247 pending_locate_frame = target_frame;
1248 pending_locate_roll = with_roll;
1249 pending_locate_flush = with_flush;
1254 // Update Timecode time
1255 _transport_frame = target_frame;
1256 _last_roll_or_reversal_location = target_frame;
1257 timecode_time(_transport_frame, transmitting_timecode_time);
1259 /* do "stopped" stuff if:
1261 * we are rolling AND
1262 * no autoplay in effect AND
1263 * we're not going to keep rolling after the locate AND
1264 * !(playing a loop with JACK sync)
1268 bool transport_was_stopped = !transport_rolling();
1270 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1271 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1272 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1273 transport_was_stopped = true;
1275 /* otherwise tell the world that we located */
1279 if (force || !for_loop_enabled || loop_changing) {
1281 PostTransportWork todo = PostTransportLocate;
1283 if (with_roll && transport_was_stopped) {
1284 todo = PostTransportWork (todo | PostTransportRoll);
1287 add_post_transport_work (todo);
1292 /* this is functionally what clear_clicks() does but with a tentative lock */
1294 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1296 if (clickm.locked()) {
1298 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1307 /* switch from input if we're going to roll */
1308 if (Config->get_monitoring_model() == HardwareMonitoring) {
1309 set_track_monitor_input_status (!config.get_auto_input());
1312 /* otherwise we're going to stop, so do the opposite */
1313 if (Config->get_monitoring_model() == HardwareMonitoring) {
1314 set_track_monitor_input_status (true);
1318 /* cancel looped playback if transport pos outside of loop range */
1321 Location* al = _locations->auto_loop_location();
1324 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1326 // located outside the loop: cancel looping directly, this is called from event handling context
1328 have_looped = false;
1330 if (!Config->get_loop_is_mode()) {
1331 set_play_loop (false, _transport_speed);
1333 if (Config->get_seamless_loop()) {
1334 /* this will make the non_realtime_locate() in the butler
1335 which then causes seek() in tracks actually do the right
1338 set_track_loop (false);
1342 } else if (_transport_frame == al->start()) {
1344 // located to start of loop - this is looping, basically
1348 if (_last_roll_location != al->start()) {
1349 /* didn't start at loop start - playback must have
1350 * started before loop since we've now hit the loop
1353 add_post_transport_work (PostTransportLocate);
1359 boost::shared_ptr<RouteList> rl = routes.reader();
1361 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1362 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1364 if (tr && tr->rec_enable_control()->get_value()) {
1365 // tell it we've looped, so it can deal with the record state
1366 tr->transport_looped (_transport_frame);
1371 TransportLooped(); // EMIT SIGNAL
1377 _butler->schedule_transport_work ();
1380 loop_changing = false;
1382 _send_timecode_update = true;
1385 send_mmc_locate (_transport_frame);
1388 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1389 if (!synced_to_engine () || _transport_frame == _engine.transport_frame ()) {
1390 Located (); /* EMIT SIGNAL */
1394 /** Set the transport speed.
1395 * Called from the process thread.
1396 * @param speed New speed
1399 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1401 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1402 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1404 if (_transport_speed == speed) {
1405 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1406 _default_transport_speed = 1.0;
1411 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1412 /* no varispeed during recording */
1413 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1414 _transport_speed, _transport_frame));
1418 _target_transport_speed = fabs(speed);
1420 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1421 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1425 speed = min (8.0, speed);
1426 } else if (speed < 0) {
1427 speed = max (-8.0, speed);
1430 if (transport_rolling() && speed == 0.0) {
1432 /* we are rolling and we want to stop */
1434 if (Config->get_monitoring_model() == HardwareMonitoring) {
1435 set_track_monitor_input_status (true);
1438 if (synced_to_engine ()) {
1440 /* do this here because our response to the slave won't
1443 _play_range = false;
1444 _count_in_once = false;
1447 _engine.transport_stop ();
1449 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1451 if (!auto_return_enabled) {
1452 _requested_return_frame = destination_frame;
1455 stop_transport (abort);
1458 } else if (transport_stopped() && speed == 1.0) {
1460 _default_transport_speed = speed;
1462 /* we are stopped and we want to start rolling at speed 1 */
1464 if (Config->get_loop_is_mode() && play_loop) {
1466 Location *location = _locations->auto_loop_location();
1468 if (location != 0) {
1469 if (_transport_frame != location->start()) {
1471 if (Config->get_seamless_loop()) {
1472 /* force tracks to do their thing */
1473 set_track_loop (true);
1476 /* jump to start and then roll from there */
1478 request_locate (location->start(), true);
1484 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1485 set_track_monitor_input_status (false);
1488 if (synced_to_engine()) {
1489 _engine.transport_start ();
1490 _count_in_once = false;
1497 /* not zero, not 1.0 ... varispeed */
1499 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1500 warning << string_compose (
1501 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1507 if (actively_recording()) {
1511 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1515 if (speed < 0.0 && _transport_frame == 0) {
1521 /* if we are reversing relative to the current speed, or relative to the speed
1522 before the last stop, then we have to do extra work.
1525 PostTransportWork todo = PostTransportWork (0);
1527 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1528 todo = PostTransportWork (todo | PostTransportReverse);
1529 _last_roll_or_reversal_location = _transport_frame;
1532 _last_transport_speed = _transport_speed;
1533 _transport_speed = speed;
1536 _default_transport_speed = speed;
1539 boost::shared_ptr<RouteList> rl = routes.reader();
1540 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1541 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1542 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1543 todo = PostTransportWork (todo | PostTransportSpeed);
1548 add_post_transport_work (todo);
1549 _butler->schedule_transport_work ();
1552 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1554 /* throttle signal emissions.
1555 * when slaved [_last]_transport_speed
1556 * usually changes every cycle (tiny amounts due to DLL).
1557 * Emitting a signal every cycle is overkill and unwarranted.
1559 * Using _last_transport_speed is not acceptable,
1560 * since it allows for large changes over a long period
1561 * of time. Hence we introduce a dedicated variable to keep track
1563 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1564 * for TransportStateChange() here is the ShuttleControl display.
1566 if (fabs (_signalled_varispeed - speed) > .002
1567 // still, signal hard changes to 1.0 and 0.0:
1568 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1569 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1572 TransportStateChange (); /* EMIT SIGNAL */
1573 _signalled_varispeed = speed;
1579 /** Stop the transport. */
1581 Session::stop_transport (bool abort, bool clear_state)
1583 _count_in_once = false;
1584 if (_transport_speed == 0.0f) {
1588 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1590 if (!get_transport_declick_required()) {
1592 /* stop has not yet been scheduled */
1594 boost::shared_ptr<RouteList> rl = routes.reader();
1595 framepos_t stop_target = audible_frame();
1597 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1598 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1600 tr->prepare_to_stop (_transport_frame, stop_target);
1606 if (actively_recording() && /* we are recording */
1607 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1609 /* we need to capture the audio that is still somewhere in the pipeline between
1610 wherever it was generated and the process callback. This means that even though
1611 the user (or something else) has asked us to stop, we have to roll
1612 past this point and then reset the playhead/transport location to
1613 the position at which the stop was requested.
1615 we still need playback to "stop" now, however, which is why we schedule
1619 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1620 _transport_frame, _worst_input_latency,
1621 _transport_frame + _worst_input_latency,
1624 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1625 _transport_frame + _worst_input_latency,
1630 /* request a declick at the start of the next process cycle() so that playback ceases.
1631 It will remain silent until we actually stop (at the StopOnce event somewhere in
1632 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1633 does not stop the transport too early.
1635 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1639 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1641 new_bits = PendingDeclickOut;
1642 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1645 /* we'll be called again after the declick */
1646 transport_sub_state = SubState (transport_sub_state|new_bits);
1647 pending_abort = abort;
1653 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1655 /* declick was scheduled, but we've been called again, which means it is really time to stop
1657 XXX: we should probably split this off into its own method and call it explicitly.
1660 realtime_stop (abort, clear_state);
1661 _butler->schedule_transport_work ();
1665 /** Called from the process thread */
1667 Session::start_transport ()
1669 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1671 _last_roll_location = _transport_frame;
1672 _last_roll_or_reversal_location = _transport_frame;
1674 have_looped = false;
1676 /* if record status is Enabled, move it to Recording. if its
1677 already Recording, move it to Disabled.
1680 switch (record_status()) {
1682 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1689 disable_record (false);
1697 transport_sub_state |= PendingDeclickIn;
1699 _transport_speed = _default_transport_speed;
1700 _target_transport_speed = _transport_speed;
1702 boost::shared_ptr<RouteList> rl = routes.reader();
1703 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1704 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1706 tr->realtime_set_speed (tr->speed(), true);
1710 if (!_engine.freewheeling()) {
1711 Timecode::Time time;
1712 timecode_time_subframes (_transport_frame, time);
1713 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1714 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1717 if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
1718 _count_in_once = false;
1719 /* calculate count-in duration (in audio samples)
1720 * - use [fixed] tempo/meter at _transport_frame
1721 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1723 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1724 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1726 const double num = meter.divisions_per_bar ();
1727 const double den = meter.note_divisor ();
1728 const double barbeat = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * den / (4. * num);
1729 const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
1731 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1733 double dt = _count_in_samples / num;
1734 if (bar_fract == 0) {
1735 /* at bar boundary, count-in 2 bars before start. */
1736 _count_in_samples *= 2;
1738 /* beats left after full bar until roll position */
1739 _count_in_samples *= 1. + bar_fract;
1743 framepos_t cf = _transport_frame - _count_in_samples;
1744 while (cf < _transport_frame) {
1745 add_click (cf - _worst_track_latency, clickbeat == 0);
1747 clickbeat = fmod (clickbeat + 1, num);
1752 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1753 TransportStateChange (); /* EMIT SIGNAL */
1756 /** Do any transport work in the audio thread that needs to be done after the
1757 * transport thread is finished. Audio thread, realtime safe.
1760 Session::post_transport ()
1762 PostTransportWork ptw = post_transport_work ();
1764 if (ptw & PostTransportAudition) {
1765 if (auditioner && auditioner->auditioning()) {
1766 process_function = &Session::process_audition;
1768 process_function = &Session::process_with_events;
1772 if (ptw & PostTransportStop) {
1774 transport_sub_state = 0;
1777 if (ptw & PostTransportLocate) {
1779 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1780 _count_in_once = false;
1783 transport_sub_state = 0;
1788 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1791 set_post_transport_work (PostTransportWork (0));
1795 Session::reset_rf_scale (framecnt_t motion)
1797 cumulative_rf_motion += motion;
1799 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1801 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1803 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1815 Session::mtc_status_changed (bool yn)
1817 g_atomic_int_set (&_mtc_active, yn);
1818 MTCSyncStateChanged( yn );
1822 Session::ltc_status_changed (bool yn)
1824 g_atomic_int_set (&_ltc_active, yn);
1825 LTCSyncStateChanged( yn );
1829 Session::use_sync_source (Slave* new_slave)
1831 /* Runs in process() context */
1833 bool non_rt_required = false;
1835 /* XXX this deletion is problematic because we're in RT context */
1840 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1842 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1843 MTCSyncStateChanged(mtc_slave->locked() );
1845 if (g_atomic_int_get (&_mtc_active) ){
1846 g_atomic_int_set (&_mtc_active, 0);
1847 MTCSyncStateChanged( false );
1849 mtc_status_connection.disconnect ();
1852 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1854 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1855 LTCSyncStateChanged (ltc_slave->locked() );
1857 if (g_atomic_int_get (&_ltc_active) ){
1858 g_atomic_int_set (&_ltc_active, 0);
1859 LTCSyncStateChanged( false );
1861 ltc_status_connection.disconnect ();
1864 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1866 // need to queue this for next process() cycle
1867 _send_timecode_update = true;
1869 boost::shared_ptr<RouteList> rl = routes.reader();
1870 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1871 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1872 if (tr && !tr->hidden()) {
1873 if (tr->realtime_set_speed (tr->speed(), true)) {
1874 non_rt_required = true;
1876 tr->set_slaved (_slave != 0);
1880 if (non_rt_required) {
1881 add_post_transport_work (PostTransportSpeed);
1882 _butler->schedule_transport_work ();
1889 Session::drop_sync_source ()
1891 request_sync_source (0);
1895 Session::switch_to_sync_source (SyncSource src)
1899 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1903 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1908 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1911 catch (failed_constructor& err) {
1917 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1922 new_slave = new LTC_Slave (*this);
1925 catch (failed_constructor& err) {
1932 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1937 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1940 catch (failed_constructor& err) {
1946 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1950 if (config.get_video_pullup() != 0.0f) {
1954 new_slave = new Engine_Slave (*AudioEngine::instance());
1962 request_sync_source (new_slave);
1966 Session::set_track_speed (Track* track, double speed)
1968 if (track->realtime_set_speed (speed, false)) {
1969 add_post_transport_work (PostTransportSpeed);
1970 _butler->schedule_transport_work ();
1976 Session::unset_play_range ()
1978 _play_range = false;
1979 _clear_event_type (SessionEvent::RangeStop);
1980 _clear_event_type (SessionEvent::RangeLocate);
1984 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1988 /* Called from event-processing context */
1990 unset_play_range ();
1992 if (range.empty()) {
1993 /* _play_range set to false in unset_play_range()
1995 if (!leave_rolling) {
1996 /* stop transport */
1997 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
2005 /* cancel loop play */
2008 list<AudioRange>::size_type sz = range.size();
2012 list<AudioRange>::iterator i = range.begin();
2013 list<AudioRange>::iterator next;
2015 while (i != range.end()) {
2020 /* locating/stopping is subject to delays for declicking.
2023 framepos_t requested_frame = i->end;
2025 if (requested_frame > current_block_size) {
2026 requested_frame -= current_block_size;
2028 requested_frame = 0;
2031 if (next == range.end()) {
2032 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
2034 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2042 } else if (sz == 1) {
2044 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2049 /* save range so we can do auto-return etc. */
2051 current_audio_range = range;
2053 /* now start rolling at the right place */
2055 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2058 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2059 TransportStateChange ();
2063 Session::request_bounded_roll (framepos_t start, framepos_t end)
2065 AudioRange ar (start, end, 0);
2066 list<AudioRange> lar;
2069 request_play_range (&lar, true);
2073 Session::set_requested_return_frame (framepos_t return_to)
2075 _requested_return_frame = return_to;
2079 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2081 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2082 ev->target2_frame = start;
2087 Session::engine_halted ()
2091 /* there will be no more calls to process(), so
2092 we'd better clean up for ourselves, right now.
2094 but first, make sure the butler is out of
2102 realtime_stop (false, true);
2103 non_realtime_stop (false, 0, ignored);
2104 transport_sub_state = 0;
2106 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2107 TransportStateChange (); /* EMIT SIGNAL */
2112 Session::xrun_recovery ()
2116 Xrun (_transport_frame); /* EMIT SIGNAL */
2118 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2120 /* it didn't actually halt, but we need
2121 to handle things in the same way.
2129 Session::route_processors_changed (RouteProcessorChange c)
2131 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2135 if (c.type == RouteProcessorChange::MeterPointChange) {
2140 if (c.type == RouteProcessorChange::RealTimeChange) {
2145 update_latency_compensation ();
2152 Session::allow_auto_play (bool yn)
2154 auto_play_legal = yn;
2158 Session::maybe_stop (framepos_t limit)
2160 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2161 if (synced_to_engine () && config.get_jack_time_master ()) {
2162 _engine.transport_stop ();
2163 } else if (!synced_to_engine ()) {
2172 Session::send_mmc_locate (framepos_t t)
2178 if (!_engine.freewheeling()) {
2179 Timecode::Time time;
2180 timecode_time_subframes (t, time);
2181 send_immediate_mmc (MIDI::MachineControlCommand (time));
2185 /** Ask the transport to not send timecode until further notice. The suspension
2186 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2187 * should be checked by the caller to find out when.
2190 Session::request_suspend_timecode_transmission ()
2192 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2197 Session::request_resume_timecode_transmission ()
2199 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2204 Session::timecode_transmission_suspended () const
2206 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;