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/disk_reader.h"
45 #include "ardour/location.h"
46 #include "ardour/profile.h"
47 #include "ardour/scene_changer.h"
48 #include "ardour/session.h"
49 #include "ardour/slave.h"
50 #include "ardour/tempo.h"
51 #include "ardour/operations.h"
52 #include "ardour/vca.h"
53 #include "ardour/vca_manager.h"
58 using namespace ARDOUR;
62 Session::add_post_transport_work (PostTransportWork ptw)
64 PostTransportWork oldval;
65 PostTransportWork newval;
69 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
70 newval = PostTransportWork (oldval | ptw);
71 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
77 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
81 Session::request_sync_source (Slave* new_slave)
83 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
86 seamless = Config->get_seamless_loop ();
88 if (dynamic_cast<Engine_Slave*>(new_slave)) {
89 /* JACK cannot support seamless looping at present */
90 Config->set_seamless_loop (false);
92 /* reset to whatever the value was before we last switched slaves */
93 Config->set_seamless_loop (_was_seamless);
96 /* save value of seamless from before the switch */
97 _was_seamless = seamless;
99 ev->slave = new_slave;
100 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
105 Session::request_transport_speed (double speed, bool as_default)
107 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
108 ev->third_yes_or_no = as_default; // as_default
109 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
113 /** Request a new transport speed, but if the speed parameter is exactly zero then use
114 * a very small +ve value to prevent the transport actually stopping. This method should
115 * be used by callers who are varying transport speed but don't ever want to stop it.
118 Session::request_transport_speed_nonzero (double speed, bool as_default)
124 request_transport_speed (speed, as_default);
128 Session::request_stop (bool abort, bool clear_state)
130 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
131 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));
136 Session::request_locate (framepos_t target_frame, bool with_roll)
138 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
139 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
144 Session::force_locate (framepos_t target_frame, bool with_roll)
146 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
147 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
152 Session::unset_preroll_record_punch ()
154 if (_preroll_record_punch_pos >= 0) {
155 remove_event (_preroll_record_punch_pos, SessionEvent::RecordStart);
157 _preroll_record_punch_pos = -1;
161 Session::unset_preroll_record_trim ()
163 _preroll_record_trim_len = 0;
167 Session::request_preroll_record_punch (framepos_t rec_in, framecnt_t preroll)
169 if (actively_recording ()) {
172 unset_preroll_record_punch ();
173 unset_preroll_record_trim ();
174 framepos_t start = std::max ((framepos_t)0, rec_in - preroll);
176 _preroll_record_punch_pos = rec_in;
177 if (_preroll_record_punch_pos >= 0) {
178 replace_event (SessionEvent::RecordStart, _preroll_record_punch_pos);
179 config.set_punch_in (false);
180 config.set_punch_out (false);
182 maybe_enable_record ();
183 request_locate (start, true);
184 set_requested_return_frame (rec_in);
188 Session::request_preroll_record_trim (framepos_t rec_in, framecnt_t preroll)
190 if (actively_recording ()) {
193 unset_preroll_record_punch ();
194 unset_preroll_record_trim ();
196 config.set_punch_in (false);
197 config.set_punch_out (false);
199 framepos_t pos = std::max ((framepos_t)0, rec_in - preroll);
200 _preroll_record_trim_len = preroll;
201 maybe_enable_record ();
202 request_locate (pos, true);
203 set_requested_return_frame (rec_in);
207 Session::request_count_in_record ()
209 if (actively_recording ()) {
212 if (transport_rolling()) {
215 maybe_enable_record ();
216 _count_in_once = true;
217 request_transport_speed (1.0, true);
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 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
434 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
436 tr->adjust_playback_buffering ();
437 /* and refill those buffers ... */
439 (*i)->non_realtime_locate (_transport_frame);
441 VCAList v = _vca_manager->vcas ();
442 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
443 (*i)->non_realtime_locate (_transport_frame);
447 if (ptw & PostTransportAdjustCaptureBuffering) {
448 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
449 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
451 tr->adjust_capture_buffering ();
456 if (ptw & PostTransportCurveRealloc) {
457 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
458 (*i)->curve_reallocate();
462 if (ptw & PostTransportSpeed) {
463 non_realtime_set_speed ();
466 if (ptw & PostTransportReverse) {
469 cumulative_rf_motion = 0;
472 /* don't seek if locate will take care of that in non_realtime_stop() */
474 if (!(ptw & PostTransportLocate)) {
475 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
476 (*i)->non_realtime_locate (_transport_frame);
478 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
479 /* new request, stop seeking, and start again */
480 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
484 VCAList v = _vca_manager->vcas ();
485 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
486 (*i)->non_realtime_locate (_transport_frame);
491 if (ptw & PostTransportLocate) {
492 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
493 non_realtime_locate ();
496 if (ptw & PostTransportStop) {
497 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
499 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
504 if (ptw & PostTransportOverWrite) {
505 non_realtime_overwrite (on_entry, finished);
507 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
512 if (ptw & PostTransportAudition) {
513 non_realtime_set_audition ();
516 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
518 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs @ %2 trw = %3\n"), g_get_monotonic_time() - before, _transport_frame, _butler->transport_work_requested()));
522 Session::non_realtime_set_speed ()
524 boost::shared_ptr<RouteList> rl = routes.reader();
525 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
526 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
528 tr->non_realtime_speed_change ();
534 Session::non_realtime_overwrite (int on_entry, bool& finished)
536 boost::shared_ptr<RouteList> rl = routes.reader();
537 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
538 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
539 if (tr && tr->pending_overwrite ()) {
540 tr->overwrite_existing_buffers ();
542 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
551 Session::non_realtime_locate ()
553 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
555 if (Config->get_loop_is_mode() && get_play_loop()) {
557 Location *loc = _locations->auto_loop_location();
559 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
560 /* jumped out of loop range: stop tracks from looping,
561 but leave loop (mode) enabled.
563 set_track_loop (false);
565 } else if (loc && Config->get_seamless_loop() &&
566 ((loc->start() <= _transport_frame) ||
567 (loc->end() > _transport_frame) ) ) {
569 /* jumping to start of loop. This might have been done before but it is
570 * idempotent and cheap. Doing it here ensures that when we start playback
571 * outside the loop we still flip tracks into the magic seamless mode
574 set_track_loop (true);
577 set_track_loop (false);
582 /* no more looping .. should have been noticed elsewhere */
586 microseconds_t begin = get_microseconds ();
590 boost::shared_ptr<RouteList> rl = routes.reader();
593 gint sc = g_atomic_int_get (&_seek_counter);
594 tf = _transport_frame;
596 cerr << "\n\n >>> START Non-RT locate on routes to " << tf << "\n\n";
598 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
599 (*i)->non_realtime_locate (tf);
600 if (sc != g_atomic_int_get (&_seek_counter)) {
601 cerr << "\n\n RESTART locate, new seek delivered\n";
606 cerr << "\n\n <<< DONE Non-RT locate on routes\n\n";
610 /* VCAs are quick to locate because they have no data (except
611 automation) associated with them. Don't bother with a
612 restart mechanism here, but do use the same transport frame
613 that the Routes used.
615 VCAList v = _vca_manager->vcas ();
616 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
617 (*i)->non_realtime_locate (tf);
621 microseconds_t end = get_microseconds ();
622 cerr << "Locate took " << setprecision (3) << ((end - begin) /1000000.0) << " secs\n";
624 _scene_changer->locate (_transport_frame);
626 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
627 rather than clearing them so that the RT thread has to spend time constructing
628 them (in Session::click).
633 #ifdef USE_TRACKS_CODE_FEATURES
635 Session::select_playhead_priority_target (framepos_t& jump_to)
639 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
645 if (Profile->get_trx() && transport_rolling() ) {
646 // We're playing, so do nothing.
647 // Next stop will put us where we need to be.
651 /* Note that the order of checking each AutoReturnTarget flag defines
652 the priority each flag.
654 Ardour/Mixbus: Last Locate
659 Tracks: Range Selection
665 if (autoreturn & RangeSelectionStart) {
666 if (!_range_selection.empty()) {
667 jump_to = _range_selection.from;
669 if (transport_rolling ()) {
670 /* Range selection no longer exists, but we're playing,
671 so do nothing. Next stop will put us where
679 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
680 /* don't try to handle loop play when synced to JACK */
682 if (!synced_to_engine()) {
683 Location *location = _locations->auto_loop_location();
686 jump_to = location->start();
688 if (Config->get_seamless_loop()) {
689 /* need to get track buffers reloaded */
690 set_track_loop (true);
696 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
697 if (!_object_selection.empty()) {
698 jump_to = _object_selection.from;
702 if (jump_to < 0 && (autoreturn & LastLocate)) {
703 jump_to = _last_roll_location;
711 Session::select_playhead_priority_target (framepos_t& jump_to)
713 if (config.get_external_sync() || !config.get_auto_return()) {
717 jump_to = _last_roll_location;
724 Session::follow_playhead_priority ()
728 if (select_playhead_priority_target (target)) {
729 request_locate (target);
734 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
740 PostTransportWork ptw = post_transport_work();
745 boost::shared_ptr<RouteList> rl = routes.reader();
746 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
747 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
748 if (tr && tr->get_captured_frames () != 0) {
754 /* stop and locate are merged here because they share a lot of common stuff */
757 now = localtime (&xnow);
760 auditioner->cancel_audition ();
763 cumulative_rf_motion = 0;
767 begin_reversible_command (Operations::capture);
768 _have_captured = true;
771 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
773 if (abort && did_record) {
774 /* no reason to save the session file when we remove sources
776 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
779 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
780 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
782 tr->transport_stopped_wallclock (*now, xnow, abort);
786 if (abort && did_record) {
787 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
790 boost::shared_ptr<RouteList> r = routes.reader ();
792 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
793 if (!(*i)->is_auditioner()) {
794 (*i)->set_pending_declick (0);
799 commit_reversible_command ();
800 /* increase take name */
801 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
802 string newname = config.get_take_name();
803 config.set_take_name(bump_name_number (newname));
807 if (_engine.running()) {
808 PostTransportWork ptw = post_transport_work ();
810 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
811 (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
813 VCAList v = _vca_manager->vcas ();
814 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
815 (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
818 update_latency_compensation ();
821 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
823 if (auto_return_enabled ||
824 (ptw & PostTransportLocate) ||
825 (_requested_return_frame >= 0) ||
826 synced_to_engine()) {
828 if (pending_locate_flush) {
829 flush_all_inserts ();
832 // rg: what is the logic behind this case?
833 // _requested_return_frame should be ignored when synced_to_engine/slaved.
834 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
836 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
837 !(ptw & PostTransportLocate)) {
839 /* no explicit locate queued */
841 bool do_locate = false;
843 if (_requested_return_frame >= 0) {
845 /* explicit return request pre-queued in event list. overrides everything else */
847 _transport_frame = _requested_return_frame;
853 if (select_playhead_priority_target (jump_to)) {
855 _transport_frame = jump_to;
860 _transport_frame = _last_roll_location;
865 _requested_return_frame = -1;
868 _engine.transport_locate (_transport_frame);
875 unset_preroll_record_trim ();
877 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
880 if (ptw & PostTransportClearSubstate) {
882 if (!Config->get_loop_is_mode()) {
887 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
890 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
891 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
892 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
893 (*i)->non_realtime_locate (_transport_frame);
895 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
897 /* we will be back */
904 VCAList v = _vca_manager->vcas ();
905 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
906 (*i)->non_realtime_locate (_transport_frame);
912 /* don't bother with this stuff if we're disconnected from the engine,
913 because there will be no process callbacks to deliver stuff from
916 if (_engine.connected() && !_engine.freewheeling()) {
917 // need to queue this in the next RT cycle
918 _send_timecode_update = true;
920 if (!dynamic_cast<MTC_Slave*>(_slave)) {
921 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
923 /* This (::non_realtime_stop()) gets called by main
924 process thread, which will lead to confusion
925 when calling AsyncMIDIPort::write().
927 Something must be done. XXX
929 send_mmc_locate (_transport_frame);
933 if ((ptw & PostTransportLocate) && get_record_enabled()) {
934 /* This is scheduled by realtime_stop(), which is also done
935 * when a slave requests /locate/ for an initial sync.
936 * We can't hold up the slave for long with a save() here,
937 * without breaking its initial sync cycle.
939 * save state only if there's no slave or if it's not yet locked.
941 if (!_slave || !_slave->locked()) {
942 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
943 SaveSessionRequested (_current_snapshot_name);
948 /* always try to get rid of this */
950 remove_pending_capture_state ();
952 /* save the current state of things if appropriate */
954 if (did_record && !saved) {
955 SaveSessionRequested (_current_snapshot_name);
958 if (ptw & PostTransportStop) {
960 if (!Config->get_loop_is_mode()) {
965 PositionChanged (_transport_frame); /* EMIT SIGNAL */
966 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
967 TransportStateChange (); /* EMIT SIGNAL */
968 AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
970 /* and start it up again if relevant */
972 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
973 request_transport_speed (1.0);
976 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
977 around for next time.
979 pending_locate_roll = false;
983 Session::check_declick_out ()
985 bool locate_required = transport_sub_state & PendingLocate;
987 /* this is called after a process() iteration. if PendingDeclickOut was set,
988 it means that we were waiting to declick the output (which has just been
989 done) before maybe doing something else. this is where we do that "something else".
991 note: called from the audio thread.
994 if (transport_sub_state & PendingDeclickOut) {
996 if (locate_required) {
997 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
998 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1000 if (!(transport_sub_state & StopPendingCapture)) {
1001 stop_transport (pending_abort);
1002 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1006 } else if (transport_sub_state & PendingLoopDeclickOut) {
1007 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
1008 transport_sub_state &= ~PendingLoopDeclickOut;
1013 Session::unset_play_loop ()
1017 clear_events (SessionEvent::AutoLoop);
1018 clear_events (SessionEvent::AutoLoopDeclick);
1019 set_track_loop (false);
1022 if (Config->get_seamless_loop()) {
1023 /* likely need to flush track buffers: this will locate us to wherever we are */
1024 add_post_transport_work (PostTransportLocate);
1025 _butler->schedule_transport_work ();
1031 Session::set_track_loop (bool yn)
1033 Location* loc = _locations->auto_loop_location ();
1039 boost::shared_ptr<RouteList> rl = routes.reader ();
1041 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1042 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1043 if (tr && !tr->is_private_route()) {
1044 tr->set_loop (yn ? loc : 0);
1050 Session::set_play_loop (bool yn, double speed)
1052 /* Called from event-handling context */
1056 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1057 /* nothing to do, or can't change loop status while recording */
1061 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1062 warning << string_compose (
1063 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1064 "Recommend changing the configured options"), PROGRAM_NAME)
1072 have_looped = false;
1076 unset_play_range ();
1078 if (Config->get_seamless_loop()) {
1079 if (!Config->get_loop_is_mode()) {
1080 /* set all tracks to use internal looping */
1081 set_track_loop (true);
1083 /* we will do this in the locate to the start OR when we hit the end
1084 * of the loop for the first time
1088 /* set all tracks to NOT use internal looping */
1089 set_track_loop (false);
1092 /* Put the delick and loop events in into the event list. The declick event will
1093 cause a de-clicking fade-out just before the end of the loop, and it will also result
1094 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1099 auto_loop_declick_range (loc, dcp, dcl);
1100 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1101 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1103 /* if requested to roll, locate to start of loop and
1104 * roll but ONLY if we're not already rolling.
1106 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1109 if (Config->get_loop_is_mode()) {
1110 /* loop IS a transport mode: if already
1111 rolling, do not locate to loop start.
1113 if (!transport_rolling() && (speed != 0.0)) {
1114 start_locate (loc->start(), true, true, false, true);
1118 start_locate (loc->start(), true, true, false, true);
1128 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1129 TransportStateChange ();
1132 Session::flush_all_inserts ()
1134 boost::shared_ptr<RouteList> r = routes.reader ();
1136 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1137 (*i)->flush_processors ();
1142 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1144 if (target_frame < 0) {
1145 error << _("Locate called for negative sample position - ignored") << endmsg;
1149 if (synced_to_engine()) {
1154 _slave->speed_and_position (sp, pos);
1156 if (target_frame != pos) {
1158 if (config.get_jack_time_master()) {
1159 /* actually locate now, since otherwise jack_timebase_callback
1160 will use the incorrect _transport_frame and report an old
1161 and incorrect time to Jack transport
1163 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1166 /* tell JACK to change transport position, and we will
1167 follow along later in ::follow_slave()
1170 _engine.transport_locate (target_frame);
1172 if (sp != 1.0f && with_roll) {
1173 _engine.transport_start ();
1179 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1184 Session::micro_locate (framecnt_t distance)
1186 boost::shared_ptr<RouteList> rl = routes.reader();
1187 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1188 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1189 if (tr && !tr->can_internal_playback_seek (distance)) {
1194 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1195 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1197 tr->internal_playback_seek (distance);
1201 _transport_frame += distance;
1205 /** @param with_mmc true to send a MMC locate command when the locate is done */
1207 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1209 bool need_butler = false;
1211 /* Locates for seamless looping are fairly different from other
1212 * locates. They assume that the diskstream buffers for each track
1213 * already have the correct data in them, and thus there is no need to
1214 * actually tell the tracks to locate. What does need to be done,
1215 * though, is all the housekeeping that is associated with non-linear
1216 * changes in the value of _transport_frame.
1219 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1220 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1222 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1224 /* already at the desired position. Not forced to locate,
1225 the loop isn't changing, so unless we're told to
1226 start rolling also, there's nothing to do but
1227 tell the world where we are (again).
1231 set_transport_speed (1.0, 0, false);
1233 loop_changing = false;
1234 Located (); /* EMIT SIGNAL */
1238 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1239 /* Schedule a declick. We'll be called again when its done.
1240 We only do it this way for ordinary locates, not those
1241 due to **seamless** loops.
1244 if (!(transport_sub_state & PendingDeclickOut)) {
1245 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1246 pending_locate_frame = target_frame;
1247 pending_locate_roll = with_roll;
1248 pending_locate_flush = with_flush;
1253 // Update Timecode time
1254 _transport_frame = target_frame;
1255 // Bump seek counter so that any in-process locate in the butler
1256 // thread(s?) can restart.
1257 g_atomic_int_inc (&_seek_counter);
1258 _last_roll_or_reversal_location = target_frame;
1259 timecode_time(_transport_frame, transmitting_timecode_time);
1261 /* do "stopped" stuff if:
1263 * we are rolling AND
1264 * no autoplay in effect AND
1265 * we're not going to keep rolling after the locate AND
1266 * !(playing a loop with JACK sync)
1270 bool transport_was_stopped = !transport_rolling();
1272 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1273 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1274 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1275 transport_was_stopped = true;
1277 /* otherwise tell the world that we located */
1281 if (force || !for_loop_enabled || loop_changing) {
1283 PostTransportWork todo = PostTransportLocate;
1285 if (with_roll && transport_was_stopped) {
1286 todo = PostTransportWork (todo | PostTransportRoll);
1289 add_post_transport_work (todo);
1294 /* this is functionally what clear_clicks() does but with a tentative lock */
1296 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1298 if (clickm.locked()) {
1300 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1309 /* switch from input if we're going to roll */
1310 if (Config->get_monitoring_model() == HardwareMonitoring) {
1311 set_track_monitor_input_status (!config.get_auto_input());
1314 /* otherwise we're going to stop, so do the opposite */
1315 if (Config->get_monitoring_model() == HardwareMonitoring) {
1316 set_track_monitor_input_status (true);
1320 /* cancel looped playback if transport pos outside of loop range */
1323 Location* al = _locations->auto_loop_location();
1326 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1328 // located outside the loop: cancel looping directly, this is called from event handling context
1330 have_looped = false;
1332 if (!Config->get_loop_is_mode()) {
1333 set_play_loop (false, _transport_speed);
1335 if (Config->get_seamless_loop()) {
1336 /* this will make the non_realtime_locate() in the butler
1337 which then causes seek() in tracks actually do the right
1340 set_track_loop (false);
1344 } else if (_transport_frame == al->start()) {
1346 // located to start of loop - this is looping, basically
1350 if (_last_roll_location != al->start()) {
1351 /* didn't start at loop start - playback must have
1352 * started before loop since we've now hit the loop
1355 add_post_transport_work (PostTransportLocate);
1361 boost::shared_ptr<RouteList> rl = routes.reader();
1363 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1364 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1366 if (tr && tr->rec_enable_control()->get_value()) {
1367 // tell it we've looped, so it can deal with the record state
1368 tr->transport_looped (_transport_frame);
1373 TransportLooped(); // EMIT SIGNAL
1379 _butler->schedule_transport_work ();
1382 loop_changing = false;
1384 _send_timecode_update = true;
1387 send_mmc_locate (_transport_frame);
1390 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1391 if (!synced_to_engine () || _transport_frame == _engine.transport_frame ()) {
1392 Located (); /* EMIT SIGNAL */
1396 /** Set the transport speed.
1397 * Called from the process thread.
1398 * @param speed New speed
1401 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1403 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1404 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1406 if (_transport_speed == speed) {
1407 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1408 _default_transport_speed = 1.0;
1413 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1414 /* no varispeed during recording */
1415 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1416 _transport_speed, _transport_frame));
1420 _target_transport_speed = fabs(speed);
1422 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1423 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1427 speed = min (8.0, speed);
1428 } else if (speed < 0) {
1429 speed = max (-8.0, speed);
1432 if (transport_rolling() && speed == 0.0) {
1434 /* we are rolling and we want to stop */
1436 if (Config->get_monitoring_model() == HardwareMonitoring) {
1437 set_track_monitor_input_status (true);
1440 if (synced_to_engine ()) {
1442 /* do this here because our response to the slave won't
1445 _play_range = false;
1446 _count_in_once = false;
1449 _engine.transport_stop ();
1451 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1453 if (!auto_return_enabled) {
1454 _requested_return_frame = destination_frame;
1457 stop_transport (abort);
1460 } else if (transport_stopped() && speed == 1.0) {
1462 _default_transport_speed = speed;
1464 /* we are stopped and we want to start rolling at speed 1 */
1466 if (Config->get_loop_is_mode() && play_loop) {
1468 Location *location = _locations->auto_loop_location();
1470 if (location != 0) {
1471 if (_transport_frame != location->start()) {
1473 if (Config->get_seamless_loop()) {
1474 /* force tracks to do their thing */
1475 set_track_loop (true);
1478 /* jump to start and then roll from there */
1480 request_locate (location->start(), true);
1486 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1487 set_track_monitor_input_status (false);
1490 if (synced_to_engine()) {
1491 _engine.transport_start ();
1492 _count_in_once = false;
1499 /* not zero, not 1.0 ... varispeed */
1501 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1502 warning << string_compose (
1503 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1509 if (actively_recording()) {
1513 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1517 if (speed < 0.0 && _transport_frame == 0) {
1523 /* if we are reversing relative to the current speed, or relative to the speed
1524 before the last stop, then we have to do extra work.
1527 PostTransportWork todo = PostTransportWork (0);
1529 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1530 todo = PostTransportWork (todo | PostTransportReverse);
1531 _last_roll_or_reversal_location = _transport_frame;
1534 _last_transport_speed = _transport_speed;
1535 _transport_speed = speed;
1538 _default_transport_speed = speed;
1541 boost::shared_ptr<RouteList> rl = routes.reader();
1542 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1543 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1544 if (tr && tr->realtime_speed_change()) {
1545 todo = PostTransportWork (todo | PostTransportSpeed);
1550 add_post_transport_work (todo);
1551 _butler->schedule_transport_work ();
1554 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1556 /* throttle signal emissions.
1557 * when slaved [_last]_transport_speed
1558 * usually changes every cycle (tiny amounts due to DLL).
1559 * Emitting a signal every cycle is overkill and unwarranted.
1561 * Using _last_transport_speed is not acceptable,
1562 * since it allows for large changes over a long period
1563 * of time. Hence we introduce a dedicated variable to keep track
1565 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1566 * for TransportStateChange() here is the ShuttleControl display.
1568 if (fabs (_signalled_varispeed - speed) > .002
1569 // still, signal hard changes to 1.0 and 0.0:
1570 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1571 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1574 TransportStateChange (); /* EMIT SIGNAL */
1575 _signalled_varispeed = speed;
1581 /** Stop the transport. */
1583 Session::stop_transport (bool abort, bool clear_state)
1585 _count_in_once = false;
1586 if (_transport_speed == 0.0f) {
1590 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1592 if (!get_transport_declick_required()) {
1594 /* stop has not yet been scheduled */
1596 boost::shared_ptr<RouteList> rl = routes.reader();
1597 framepos_t stop_target = audible_frame();
1599 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1600 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1602 tr->prepare_to_stop (_transport_frame, stop_target);
1608 if (actively_recording() && /* we are recording */
1609 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1611 /* we need to capture the audio that is still somewhere in the pipeline between
1612 wherever it was generated and the process callback. This means that even though
1613 the user (or something else) has asked us to stop, we have to roll
1614 past this point and then reset the playhead/transport location to
1615 the position at which the stop was requested.
1617 we still need playback to "stop" now, however, which is why we schedule
1621 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1622 _transport_frame, _worst_input_latency,
1623 _transport_frame + _worst_input_latency,
1626 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1627 _transport_frame + _worst_input_latency,
1632 /* request a declick at the start of the next process cycle() so that playback ceases.
1633 It will remain silent until we actually stop (at the StopOnce event somewhere in
1634 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1635 does not stop the transport too early.
1637 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1641 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1643 new_bits = PendingDeclickOut;
1644 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1647 /* we'll be called again after the declick */
1648 transport_sub_state = SubState (transport_sub_state|new_bits);
1649 pending_abort = abort;
1655 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1657 /* declick was scheduled, but we've been called again, which means it is really time to stop
1659 XXX: we should probably split this off into its own method and call it explicitly.
1662 realtime_stop (abort, clear_state);
1663 _butler->schedule_transport_work ();
1667 /** Called from the process thread */
1669 Session::start_transport ()
1671 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1673 _last_roll_location = _transport_frame;
1674 _last_roll_or_reversal_location = _transport_frame;
1676 have_looped = false;
1678 /* if record status is Enabled, move it to Recording. if its
1679 already Recording, move it to Disabled.
1682 switch (record_status()) {
1684 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1691 disable_record (false);
1699 transport_sub_state |= PendingDeclickIn;
1701 _transport_speed = _default_transport_speed;
1702 _target_transport_speed = _transport_speed;
1704 boost::shared_ptr<RouteList> rl = routes.reader();
1705 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1706 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1708 tr->realtime_speed_change ();
1712 if (!_engine.freewheeling()) {
1713 Timecode::Time time;
1714 timecode_time_subframes (_transport_frame, time);
1715 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1716 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1719 if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
1720 _count_in_once = false;
1721 /* calculate count-in duration (in audio samples)
1722 * - use [fixed] tempo/meter at _transport_frame
1723 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1725 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1726 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1728 const double num = meter.divisions_per_bar ();
1729 const double den = meter.note_divisor ();
1730 const double barbeat = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * den / (4. * num);
1731 const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
1733 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1735 double dt = _count_in_samples / num;
1736 if (bar_fract == 0) {
1737 /* at bar boundary, count-in 2 bars before start. */
1738 _count_in_samples *= 2;
1740 /* beats left after full bar until roll position */
1741 _count_in_samples *= 1. + bar_fract;
1745 framepos_t cf = _transport_frame - _count_in_samples;
1746 while (cf < _transport_frame) {
1747 add_click (cf - _worst_track_latency, clickbeat == 0);
1749 clickbeat = fmod (clickbeat + 1, num);
1754 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1755 TransportStateChange (); /* EMIT SIGNAL */
1758 /** Do any transport work in the audio thread that needs to be done after the
1759 * transport thread is finished. Audio thread, realtime safe.
1762 Session::post_transport ()
1764 PostTransportWork ptw = post_transport_work ();
1766 if (ptw & PostTransportAudition) {
1767 if (auditioner && auditioner->auditioning()) {
1768 process_function = &Session::process_audition;
1770 process_function = &Session::process_with_events;
1774 if (ptw & PostTransportStop) {
1776 transport_sub_state = 0;
1779 if (ptw & PostTransportLocate) {
1781 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1782 _count_in_once = false;
1785 transport_sub_state = 0;
1790 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1793 set_post_transport_work (PostTransportWork (0));
1797 Session::reset_rf_scale (framecnt_t motion)
1799 cumulative_rf_motion += motion;
1801 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1803 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1805 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1817 Session::mtc_status_changed (bool yn)
1819 g_atomic_int_set (&_mtc_active, yn);
1820 MTCSyncStateChanged( yn );
1824 Session::ltc_status_changed (bool yn)
1826 g_atomic_int_set (&_ltc_active, yn);
1827 LTCSyncStateChanged( yn );
1831 Session::use_sync_source (Slave* new_slave)
1833 /* Runs in process() context */
1835 bool non_rt_required = false;
1837 /* XXX this deletion is problematic because we're in RT context */
1843 /* slave change, reset any DiskIO block on disk output because it is no
1844 longer valid with a new slave.
1846 DiskReader::set_no_disk_output (false);
1848 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1850 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1851 MTCSyncStateChanged(mtc_slave->locked() );
1853 if (g_atomic_int_get (&_mtc_active) ){
1854 g_atomic_int_set (&_mtc_active, 0);
1855 MTCSyncStateChanged( false );
1857 mtc_status_connection.disconnect ();
1860 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1862 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1863 LTCSyncStateChanged (ltc_slave->locked() );
1865 if (g_atomic_int_get (&_ltc_active) ){
1866 g_atomic_int_set (&_ltc_active, 0);
1867 LTCSyncStateChanged( false );
1869 ltc_status_connection.disconnect ();
1872 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1874 // need to queue this for next process() cycle
1875 _send_timecode_update = true;
1877 boost::shared_ptr<RouteList> rl = routes.reader();
1878 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1879 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1880 if (tr && !tr->is_private_route()) {
1881 if (tr->realtime_speed_change()) {
1882 non_rt_required = true;
1884 tr->set_slaved (_slave != 0);
1888 if (non_rt_required) {
1889 add_post_transport_work (PostTransportSpeed);
1890 _butler->schedule_transport_work ();
1897 Session::drop_sync_source ()
1899 request_sync_source (0);
1903 Session::switch_to_sync_source (SyncSource src)
1907 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1911 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1916 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1919 catch (failed_constructor& err) {
1925 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1930 new_slave = new LTC_Slave (*this);
1933 catch (failed_constructor& err) {
1940 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1945 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1948 catch (failed_constructor& err) {
1954 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1958 if (config.get_video_pullup() != 0.0f) {
1962 new_slave = new Engine_Slave (*AudioEngine::instance());
1970 request_sync_source (new_slave);
1974 Session::unset_play_range ()
1976 _play_range = false;
1977 _clear_event_type (SessionEvent::RangeStop);
1978 _clear_event_type (SessionEvent::RangeLocate);
1982 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1986 /* Called from event-processing context */
1988 unset_play_range ();
1990 if (range.empty()) {
1991 /* _play_range set to false in unset_play_range()
1993 if (!leave_rolling) {
1994 /* stop transport */
1995 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
2003 /* cancel loop play */
2006 list<AudioRange>::size_type sz = range.size();
2010 list<AudioRange>::iterator i = range.begin();
2011 list<AudioRange>::iterator next;
2013 while (i != range.end()) {
2018 /* locating/stopping is subject to delays for declicking.
2021 framepos_t requested_frame = i->end;
2023 if (requested_frame > current_block_size) {
2024 requested_frame -= current_block_size;
2026 requested_frame = 0;
2029 if (next == range.end()) {
2030 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
2032 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2040 } else if (sz == 1) {
2042 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2047 /* save range so we can do auto-return etc. */
2049 current_audio_range = range;
2051 /* now start rolling at the right place */
2053 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2056 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2057 TransportStateChange ();
2061 Session::request_bounded_roll (framepos_t start, framepos_t end)
2063 AudioRange ar (start, end, 0);
2064 list<AudioRange> lar;
2067 request_play_range (&lar, true);
2071 Session::set_requested_return_frame (framepos_t return_to)
2073 _requested_return_frame = return_to;
2077 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2079 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2080 ev->target2_frame = start;
2085 Session::engine_halted ()
2089 /* there will be no more calls to process(), so
2090 we'd better clean up for ourselves, right now.
2092 but first, make sure the butler is out of
2100 realtime_stop (false, true);
2101 non_realtime_stop (false, 0, ignored);
2102 transport_sub_state = 0;
2104 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2105 TransportStateChange (); /* EMIT SIGNAL */
2110 Session::xrun_recovery ()
2114 Xrun (_transport_frame); /* EMIT SIGNAL */
2116 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2118 /* it didn't actually halt, but we need
2119 to handle things in the same way.
2127 Session::route_processors_changed (RouteProcessorChange c)
2129 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2133 if (c.type == RouteProcessorChange::MeterPointChange) {
2138 if (c.type == RouteProcessorChange::RealTimeChange) {
2143 update_latency_compensation ();
2150 Session::allow_auto_play (bool yn)
2152 auto_play_legal = yn;
2156 Session::maybe_stop (framepos_t limit)
2158 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2159 if (synced_to_engine () && config.get_jack_time_master ()) {
2160 _engine.transport_stop ();
2161 } else if (!synced_to_engine ()) {
2170 Session::send_mmc_locate (framepos_t t)
2176 if (!_engine.freewheeling()) {
2177 Timecode::Time time;
2178 timecode_time_subframes (t, time);
2179 send_immediate_mmc (MIDI::MachineControlCommand (time));
2183 /** Ask the transport to not send timecode until further notice. The suspension
2184 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2185 * should be checked by the caller to find out when.
2188 Session::request_suspend_timecode_transmission ()
2190 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2195 Session::request_resume_timecode_transmission ()
2197 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2202 Session::timecode_transmission_suspended () const
2204 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;