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 << " counter = " << sc << "\n\n";
598 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
599 (*i)->non_realtime_locate (tf);
601 cerr << "\t\tcounter after track: " << g_atomic_int_get (&_seek_counter) << endl;
602 if (sc != g_atomic_int_get (&_seek_counter)) {
603 cerr << "\n\n RESTART locate, new seek delivered\n";
608 cerr << "\n\n <<< DONE Non-RT locate on routes\n\n";
612 /* VCAs are quick to locate because they have no data (except
613 automation) associated with them. Don't bother with a
614 restart mechanism here, but do use the same transport frame
615 that the Routes used.
617 VCAList v = _vca_manager->vcas ();
618 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
619 (*i)->non_realtime_locate (tf);
623 microseconds_t end = get_microseconds ();
624 cerr << "Locate took " << setprecision (3) << ((end - begin) /1000000.0) << " secs\n";
626 _scene_changer->locate (_transport_frame);
628 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
629 rather than clearing them so that the RT thread has to spend time constructing
630 them (in Session::click).
635 #ifdef USE_TRACKS_CODE_FEATURES
637 Session::select_playhead_priority_target (framepos_t& jump_to)
641 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
647 if (Profile->get_trx() && transport_rolling() ) {
648 // We're playing, so do nothing.
649 // Next stop will put us where we need to be.
653 /* Note that the order of checking each AutoReturnTarget flag defines
654 the priority each flag.
656 Ardour/Mixbus: Last Locate
661 Tracks: Range Selection
667 if (autoreturn & RangeSelectionStart) {
668 if (!_range_selection.empty()) {
669 jump_to = _range_selection.from;
671 if (transport_rolling ()) {
672 /* Range selection no longer exists, but we're playing,
673 so do nothing. Next stop will put us where
681 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
682 /* don't try to handle loop play when synced to JACK */
684 if (!synced_to_engine()) {
685 Location *location = _locations->auto_loop_location();
688 jump_to = location->start();
690 if (Config->get_seamless_loop()) {
691 /* need to get track buffers reloaded */
692 set_track_loop (true);
698 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
699 if (!_object_selection.empty()) {
700 jump_to = _object_selection.from;
704 if (jump_to < 0 && (autoreturn & LastLocate)) {
705 jump_to = _last_roll_location;
713 Session::select_playhead_priority_target (framepos_t& jump_to)
715 if (config.get_external_sync() || !config.get_auto_return()) {
719 jump_to = _last_roll_location;
726 Session::follow_playhead_priority ()
730 if (select_playhead_priority_target (target)) {
731 request_locate (target);
736 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
742 PostTransportWork ptw = post_transport_work();
747 boost::shared_ptr<RouteList> rl = routes.reader();
748 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
749 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
750 if (tr && tr->get_captured_frames () != 0) {
756 /* stop and locate are merged here because they share a lot of common stuff */
759 now = localtime (&xnow);
762 auditioner->cancel_audition ();
765 cumulative_rf_motion = 0;
769 begin_reversible_command (Operations::capture);
770 _have_captured = true;
773 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
775 if (abort && did_record) {
776 /* no reason to save the session file when we remove sources
778 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
781 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
782 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
784 tr->transport_stopped_wallclock (*now, xnow, abort);
788 if (abort && did_record) {
789 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
792 boost::shared_ptr<RouteList> r = routes.reader ();
794 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
795 if (!(*i)->is_auditioner()) {
796 (*i)->set_pending_declick (0);
801 commit_reversible_command ();
802 /* increase take name */
803 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
804 string newname = config.get_take_name();
805 config.set_take_name(bump_name_number (newname));
809 if (_engine.running()) {
810 PostTransportWork ptw = post_transport_work ();
812 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
813 (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
815 VCAList v = _vca_manager->vcas ();
816 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
817 (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
820 update_latency_compensation ();
823 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
825 if (auto_return_enabled ||
826 (ptw & PostTransportLocate) ||
827 (_requested_return_frame >= 0) ||
828 synced_to_engine()) {
830 if (pending_locate_flush) {
831 flush_all_inserts ();
834 // rg: what is the logic behind this case?
835 // _requested_return_frame should be ignored when synced_to_engine/slaved.
836 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
838 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
839 !(ptw & PostTransportLocate)) {
841 /* no explicit locate queued */
843 bool do_locate = false;
845 if (_requested_return_frame >= 0) {
847 /* explicit return request pre-queued in event list. overrides everything else */
849 _transport_frame = _requested_return_frame;
855 if (select_playhead_priority_target (jump_to)) {
857 _transport_frame = jump_to;
862 _transport_frame = _last_roll_location;
867 _requested_return_frame = -1;
870 _engine.transport_locate (_transport_frame);
877 unset_preroll_record_trim ();
879 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
882 if (ptw & PostTransportClearSubstate) {
884 if (!Config->get_loop_is_mode()) {
889 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
892 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
893 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
894 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
895 (*i)->non_realtime_locate (_transport_frame);
897 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
899 /* we will be back */
906 VCAList v = _vca_manager->vcas ();
907 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
908 (*i)->non_realtime_locate (_transport_frame);
914 /* don't bother with this stuff if we're disconnected from the engine,
915 because there will be no process callbacks to deliver stuff from
918 if (_engine.connected() && !_engine.freewheeling()) {
919 // need to queue this in the next RT cycle
920 _send_timecode_update = true;
922 if (!dynamic_cast<MTC_Slave*>(_slave)) {
923 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
925 /* This (::non_realtime_stop()) gets called by main
926 process thread, which will lead to confusion
927 when calling AsyncMIDIPort::write().
929 Something must be done. XXX
931 send_mmc_locate (_transport_frame);
935 if ((ptw & PostTransportLocate) && get_record_enabled()) {
936 /* This is scheduled by realtime_stop(), which is also done
937 * when a slave requests /locate/ for an initial sync.
938 * We can't hold up the slave for long with a save() here,
939 * without breaking its initial sync cycle.
941 * save state only if there's no slave or if it's not yet locked.
943 if (!_slave || !_slave->locked()) {
944 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
945 SaveSessionRequested (_current_snapshot_name);
950 /* always try to get rid of this */
952 remove_pending_capture_state ();
954 /* save the current state of things if appropriate */
956 if (did_record && !saved) {
957 SaveSessionRequested (_current_snapshot_name);
960 if (ptw & PostTransportStop) {
962 if (!Config->get_loop_is_mode()) {
967 PositionChanged (_transport_frame); /* EMIT SIGNAL */
968 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
969 TransportStateChange (); /* EMIT SIGNAL */
970 AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
972 /* and start it up again if relevant */
974 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
975 request_transport_speed (1.0);
978 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
979 around for next time.
981 pending_locate_roll = false;
985 Session::check_declick_out ()
987 bool locate_required = transport_sub_state & PendingLocate;
989 /* this is called after a process() iteration. if PendingDeclickOut was set,
990 it means that we were waiting to declick the output (which has just been
991 done) before maybe doing something else. this is where we do that "something else".
993 note: called from the audio thread.
996 if (transport_sub_state & PendingDeclickOut) {
998 if (locate_required) {
999 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
1000 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1002 if (!(transport_sub_state & StopPendingCapture)) {
1003 stop_transport (pending_abort);
1004 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1008 } else if (transport_sub_state & PendingLoopDeclickOut) {
1009 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
1010 transport_sub_state &= ~PendingLoopDeclickOut;
1015 Session::unset_play_loop ()
1019 clear_events (SessionEvent::AutoLoop);
1020 clear_events (SessionEvent::AutoLoopDeclick);
1021 set_track_loop (false);
1024 if (Config->get_seamless_loop()) {
1025 /* likely need to flush track buffers: this will locate us to wherever we are */
1026 add_post_transport_work (PostTransportLocate);
1027 _butler->schedule_transport_work ();
1033 Session::set_track_loop (bool yn)
1035 Location* loc = _locations->auto_loop_location ();
1041 boost::shared_ptr<RouteList> rl = routes.reader ();
1043 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1044 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1045 if (tr && !tr->is_private_route()) {
1046 tr->set_loop (yn ? loc : 0);
1052 Session::set_play_loop (bool yn, double speed)
1054 /* Called from event-handling context */
1058 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1059 /* nothing to do, or can't change loop status while recording */
1063 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1064 warning << string_compose (
1065 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1066 "Recommend changing the configured options"), PROGRAM_NAME)
1074 have_looped = false;
1078 unset_play_range ();
1080 if (Config->get_seamless_loop()) {
1081 if (!Config->get_loop_is_mode()) {
1082 /* set all tracks to use internal looping */
1083 set_track_loop (true);
1085 /* we will do this in the locate to the start OR when we hit the end
1086 * of the loop for the first time
1090 /* set all tracks to NOT use internal looping */
1091 set_track_loop (false);
1094 /* Put the delick and loop events in into the event list. The declick event will
1095 cause a de-clicking fade-out just before the end of the loop, and it will also result
1096 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1101 auto_loop_declick_range (loc, dcp, dcl);
1102 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1103 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1105 /* if requested to roll, locate to start of loop and
1106 * roll but ONLY if we're not already rolling.
1108 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1111 if (Config->get_loop_is_mode()) {
1112 /* loop IS a transport mode: if already
1113 rolling, do not locate to loop start.
1115 if (!transport_rolling() && (speed != 0.0)) {
1116 start_locate (loc->start(), true, true, false, true);
1120 start_locate (loc->start(), true, true, false, true);
1130 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1131 TransportStateChange ();
1134 Session::flush_all_inserts ()
1136 boost::shared_ptr<RouteList> r = routes.reader ();
1138 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1139 (*i)->flush_processors ();
1144 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1146 if (target_frame < 0) {
1147 error << _("Locate called for negative sample position - ignored") << endmsg;
1151 if (synced_to_engine()) {
1156 _slave->speed_and_position (sp, pos);
1158 if (target_frame != pos) {
1160 if (config.get_jack_time_master()) {
1161 /* actually locate now, since otherwise jack_timebase_callback
1162 will use the incorrect _transport_frame and report an old
1163 and incorrect time to Jack transport
1165 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1168 /* tell JACK to change transport position, and we will
1169 follow along later in ::follow_slave()
1172 _engine.transport_locate (target_frame);
1174 if (sp != 1.0f && with_roll) {
1175 _engine.transport_start ();
1181 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1186 Session::micro_locate (framecnt_t distance)
1188 boost::shared_ptr<RouteList> rl = routes.reader();
1189 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1190 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1191 if (tr && !tr->can_internal_playback_seek (distance)) {
1196 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1197 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1199 tr->internal_playback_seek (distance);
1203 _transport_frame += distance;
1207 /** @param with_mmc true to send a MMC locate command when the locate is done */
1209 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1211 bool need_butler = false;
1213 /* Locates for seamless looping are fairly different from other
1214 * locates. They assume that the diskstream buffers for each track
1215 * already have the correct data in them, and thus there is no need to
1216 * actually tell the tracks to locate. What does need to be done,
1217 * though, is all the housekeeping that is associated with non-linear
1218 * changes in the value of _transport_frame.
1221 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1222 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1224 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1226 /* already at the desired position. Not forced to locate,
1227 the loop isn't changing, so unless we're told to
1228 start rolling also, there's nothing to do but
1229 tell the world where we are (again).
1233 set_transport_speed (1.0, 0, false);
1235 loop_changing = false;
1236 Located (); /* EMIT SIGNAL */
1240 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1241 /* Schedule a declick. We'll be called again when its done.
1242 We only do it this way for ordinary locates, not those
1243 due to **seamless** loops.
1246 if (!(transport_sub_state & PendingDeclickOut)) {
1247 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1248 pending_locate_frame = target_frame;
1249 pending_locate_roll = with_roll;
1250 pending_locate_flush = with_flush;
1251 cerr << "Declick scheduled ... back soon\n";
1256 cerr << "... now doing the actual locate\n";
1258 // Update Timecode time
1259 _transport_frame = target_frame;
1260 // Bump seek counter so that any in-process locate in the butler
1261 // thread(s?) can restart.
1262 g_atomic_int_inc (&_seek_counter);
1263 _last_roll_or_reversal_location = target_frame;
1264 timecode_time(_transport_frame, transmitting_timecode_time);
1266 /* do "stopped" stuff if:
1268 * we are rolling AND
1269 * no autoplay in effect AND
1270 * we're not going to keep rolling after the locate AND
1271 * !(playing a loop with JACK sync)
1275 bool transport_was_stopped = !transport_rolling();
1277 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1278 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1279 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1280 transport_was_stopped = true;
1282 /* otherwise tell the world that we located */
1286 if (force || !for_loop_enabled || loop_changing) {
1288 PostTransportWork todo = PostTransportLocate;
1290 if (with_roll && transport_was_stopped) {
1291 todo = PostTransportWork (todo | PostTransportRoll);
1294 add_post_transport_work (todo);
1299 /* this is functionally what clear_clicks() does but with a tentative lock */
1301 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1303 if (clickm.locked()) {
1305 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1314 /* switch from input if we're going to roll */
1315 if (Config->get_monitoring_model() == HardwareMonitoring) {
1316 set_track_monitor_input_status (!config.get_auto_input());
1319 /* otherwise we're going to stop, so do the opposite */
1320 if (Config->get_monitoring_model() == HardwareMonitoring) {
1321 set_track_monitor_input_status (true);
1325 /* cancel looped playback if transport pos outside of loop range */
1328 Location* al = _locations->auto_loop_location();
1331 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1333 // located outside the loop: cancel looping directly, this is called from event handling context
1335 have_looped = false;
1337 if (!Config->get_loop_is_mode()) {
1338 set_play_loop (false, _transport_speed);
1340 if (Config->get_seamless_loop()) {
1341 /* this will make the non_realtime_locate() in the butler
1342 which then causes seek() in tracks actually do the right
1345 set_track_loop (false);
1349 } else if (_transport_frame == al->start()) {
1351 // located to start of loop - this is looping, basically
1355 if (_last_roll_location != al->start()) {
1356 /* didn't start at loop start - playback must have
1357 * started before loop since we've now hit the loop
1360 add_post_transport_work (PostTransportLocate);
1366 boost::shared_ptr<RouteList> rl = routes.reader();
1368 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1369 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1371 if (tr && tr->rec_enable_control()->get_value()) {
1372 // tell it we've looped, so it can deal with the record state
1373 tr->transport_looped (_transport_frame);
1378 TransportLooped(); // EMIT SIGNAL
1384 _butler->schedule_transport_work ();
1387 loop_changing = false;
1389 _send_timecode_update = true;
1392 send_mmc_locate (_transport_frame);
1395 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1396 if (!synced_to_engine () || _transport_frame == _engine.transport_frame ()) {
1397 Located (); /* EMIT SIGNAL */
1401 /** Set the transport speed.
1402 * Called from the process thread.
1403 * @param speed New speed
1406 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1408 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1409 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1411 if (_transport_speed == speed) {
1412 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1413 _default_transport_speed = 1.0;
1418 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1419 /* no varispeed during recording */
1420 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1421 _transport_speed, _transport_frame));
1425 _target_transport_speed = fabs(speed);
1427 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1428 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1432 speed = min (8.0, speed);
1433 } else if (speed < 0) {
1434 speed = max (-8.0, speed);
1437 if (transport_rolling() && speed == 0.0) {
1439 /* we are rolling and we want to stop */
1441 if (Config->get_monitoring_model() == HardwareMonitoring) {
1442 set_track_monitor_input_status (true);
1445 if (synced_to_engine ()) {
1447 /* do this here because our response to the slave won't
1450 _play_range = false;
1451 _count_in_once = false;
1454 _engine.transport_stop ();
1456 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1458 if (!auto_return_enabled) {
1459 _requested_return_frame = destination_frame;
1462 stop_transport (abort);
1465 } else if (transport_stopped() && speed == 1.0) {
1467 _default_transport_speed = speed;
1469 /* we are stopped and we want to start rolling at speed 1 */
1471 if (Config->get_loop_is_mode() && play_loop) {
1473 Location *location = _locations->auto_loop_location();
1475 if (location != 0) {
1476 if (_transport_frame != location->start()) {
1478 if (Config->get_seamless_loop()) {
1479 /* force tracks to do their thing */
1480 set_track_loop (true);
1483 /* jump to start and then roll from there */
1485 request_locate (location->start(), true);
1491 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1492 set_track_monitor_input_status (false);
1495 if (synced_to_engine()) {
1496 _engine.transport_start ();
1497 _count_in_once = false;
1504 /* not zero, not 1.0 ... varispeed */
1506 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1507 warning << string_compose (
1508 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1514 if (actively_recording()) {
1518 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1522 if (speed < 0.0 && _transport_frame == 0) {
1528 /* if we are reversing relative to the current speed, or relative to the speed
1529 before the last stop, then we have to do extra work.
1532 PostTransportWork todo = PostTransportWork (0);
1534 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1535 todo = PostTransportWork (todo | PostTransportReverse);
1536 _last_roll_or_reversal_location = _transport_frame;
1539 _last_transport_speed = _transport_speed;
1540 _transport_speed = speed;
1543 _default_transport_speed = speed;
1546 boost::shared_ptr<RouteList> rl = routes.reader();
1547 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1548 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1549 if (tr && tr->realtime_speed_change()) {
1550 todo = PostTransportWork (todo | PostTransportSpeed);
1555 add_post_transport_work (todo);
1556 _butler->schedule_transport_work ();
1559 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1561 /* throttle signal emissions.
1562 * when slaved [_last]_transport_speed
1563 * usually changes every cycle (tiny amounts due to DLL).
1564 * Emitting a signal every cycle is overkill and unwarranted.
1566 * Using _last_transport_speed is not acceptable,
1567 * since it allows for large changes over a long period
1568 * of time. Hence we introduce a dedicated variable to keep track
1570 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1571 * for TransportStateChange() here is the ShuttleControl display.
1573 if (fabs (_signalled_varispeed - speed) > .002
1574 // still, signal hard changes to 1.0 and 0.0:
1575 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1576 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1579 TransportStateChange (); /* EMIT SIGNAL */
1580 _signalled_varispeed = speed;
1586 /** Stop the transport. */
1588 Session::stop_transport (bool abort, bool clear_state)
1590 _count_in_once = false;
1591 if (_transport_speed == 0.0f) {
1595 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1597 if (!get_transport_declick_required()) {
1599 /* stop has not yet been scheduled */
1601 boost::shared_ptr<RouteList> rl = routes.reader();
1602 framepos_t stop_target = audible_frame();
1604 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1605 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1607 tr->prepare_to_stop (_transport_frame, stop_target);
1613 if (actively_recording() && /* we are recording */
1614 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1616 /* we need to capture the audio that is still somewhere in the pipeline between
1617 wherever it was generated and the process callback. This means that even though
1618 the user (or something else) has asked us to stop, we have to roll
1619 past this point and then reset the playhead/transport location to
1620 the position at which the stop was requested.
1622 we still need playback to "stop" now, however, which is why we schedule
1626 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1627 _transport_frame, _worst_input_latency,
1628 _transport_frame + _worst_input_latency,
1631 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1632 _transport_frame + _worst_input_latency,
1637 /* request a declick at the start of the next process cycle() so that playback ceases.
1638 It will remain silent until we actually stop (at the StopOnce event somewhere in
1639 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1640 does not stop the transport too early.
1642 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1646 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1648 new_bits = PendingDeclickOut;
1649 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1652 /* we'll be called again after the declick */
1653 transport_sub_state = SubState (transport_sub_state|new_bits);
1654 pending_abort = abort;
1660 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1662 /* declick was scheduled, but we've been called again, which means it is really time to stop
1664 XXX: we should probably split this off into its own method and call it explicitly.
1667 realtime_stop (abort, clear_state);
1668 _butler->schedule_transport_work ();
1672 /** Called from the process thread */
1674 Session::start_transport ()
1676 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1678 _last_roll_location = _transport_frame;
1679 _last_roll_or_reversal_location = _transport_frame;
1681 have_looped = false;
1683 /* if record status is Enabled, move it to Recording. if its
1684 already Recording, move it to Disabled.
1687 switch (record_status()) {
1689 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1696 disable_record (false);
1704 transport_sub_state |= PendingDeclickIn;
1706 _transport_speed = _default_transport_speed;
1707 _target_transport_speed = _transport_speed;
1709 boost::shared_ptr<RouteList> rl = routes.reader();
1710 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1711 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1713 tr->realtime_speed_change ();
1717 if (!_engine.freewheeling()) {
1718 Timecode::Time time;
1719 timecode_time_subframes (_transport_frame, time);
1720 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1721 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1724 if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
1725 _count_in_once = false;
1726 /* calculate count-in duration (in audio samples)
1727 * - use [fixed] tempo/meter at _transport_frame
1728 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1730 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1731 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1733 const double num = meter.divisions_per_bar ();
1734 const double den = meter.note_divisor ();
1735 const double barbeat = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * den / (4. * num);
1736 const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
1738 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1740 double dt = _count_in_samples / num;
1741 if (bar_fract == 0) {
1742 /* at bar boundary, count-in 2 bars before start. */
1743 _count_in_samples *= 2;
1745 /* beats left after full bar until roll position */
1746 _count_in_samples *= 1. + bar_fract;
1750 framepos_t cf = _transport_frame - _count_in_samples;
1751 while (cf < _transport_frame) {
1752 add_click (cf - _worst_track_latency, clickbeat == 0);
1754 clickbeat = fmod (clickbeat + 1, num);
1759 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1760 TransportStateChange (); /* EMIT SIGNAL */
1763 /** Do any transport work in the audio thread that needs to be done after the
1764 * transport thread is finished. Audio thread, realtime safe.
1767 Session::post_transport ()
1769 PostTransportWork ptw = post_transport_work ();
1771 if (ptw & PostTransportAudition) {
1772 if (auditioner && auditioner->auditioning()) {
1773 process_function = &Session::process_audition;
1775 process_function = &Session::process_with_events;
1779 if (ptw & PostTransportStop) {
1781 transport_sub_state = 0;
1784 if (ptw & PostTransportLocate) {
1786 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1787 _count_in_once = false;
1790 transport_sub_state = 0;
1795 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1798 set_post_transport_work (PostTransportWork (0));
1802 Session::reset_rf_scale (framecnt_t motion)
1804 cumulative_rf_motion += motion;
1806 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1808 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1810 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1822 Session::mtc_status_changed (bool yn)
1824 g_atomic_int_set (&_mtc_active, yn);
1825 MTCSyncStateChanged( yn );
1829 Session::ltc_status_changed (bool yn)
1831 g_atomic_int_set (&_ltc_active, yn);
1832 LTCSyncStateChanged( yn );
1836 Session::use_sync_source (Slave* new_slave)
1838 /* Runs in process() context */
1840 bool non_rt_required = false;
1842 /* XXX this deletion is problematic because we're in RT context */
1848 /* slave change, reset any DiskIO block on disk output because it is no
1849 longer valid with a new slave.
1851 DiskReader::set_no_disk_output (false);
1853 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1855 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1856 MTCSyncStateChanged(mtc_slave->locked() );
1858 if (g_atomic_int_get (&_mtc_active) ){
1859 g_atomic_int_set (&_mtc_active, 0);
1860 MTCSyncStateChanged( false );
1862 mtc_status_connection.disconnect ();
1865 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1867 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1868 LTCSyncStateChanged (ltc_slave->locked() );
1870 if (g_atomic_int_get (&_ltc_active) ){
1871 g_atomic_int_set (&_ltc_active, 0);
1872 LTCSyncStateChanged( false );
1874 ltc_status_connection.disconnect ();
1877 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1879 // need to queue this for next process() cycle
1880 _send_timecode_update = true;
1882 boost::shared_ptr<RouteList> rl = routes.reader();
1883 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1884 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1885 if (tr && !tr->is_private_route()) {
1886 if (tr->realtime_speed_change()) {
1887 non_rt_required = true;
1889 tr->set_slaved (_slave != 0);
1893 if (non_rt_required) {
1894 add_post_transport_work (PostTransportSpeed);
1895 _butler->schedule_transport_work ();
1902 Session::drop_sync_source ()
1904 request_sync_source (0);
1908 Session::switch_to_sync_source (SyncSource src)
1912 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1916 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1921 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1924 catch (failed_constructor& err) {
1930 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1935 new_slave = new LTC_Slave (*this);
1938 catch (failed_constructor& err) {
1945 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1950 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1953 catch (failed_constructor& err) {
1959 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1963 if (config.get_video_pullup() != 0.0f) {
1967 new_slave = new Engine_Slave (*AudioEngine::instance());
1975 request_sync_source (new_slave);
1979 Session::unset_play_range ()
1981 _play_range = false;
1982 _clear_event_type (SessionEvent::RangeStop);
1983 _clear_event_type (SessionEvent::RangeLocate);
1987 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1991 /* Called from event-processing context */
1993 unset_play_range ();
1995 if (range.empty()) {
1996 /* _play_range set to false in unset_play_range()
1998 if (!leave_rolling) {
1999 /* stop transport */
2000 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
2008 /* cancel loop play */
2011 list<AudioRange>::size_type sz = range.size();
2015 list<AudioRange>::iterator i = range.begin();
2016 list<AudioRange>::iterator next;
2018 while (i != range.end()) {
2023 /* locating/stopping is subject to delays for declicking.
2026 framepos_t requested_frame = i->end;
2028 if (requested_frame > current_block_size) {
2029 requested_frame -= current_block_size;
2031 requested_frame = 0;
2034 if (next == range.end()) {
2035 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
2037 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2045 } else if (sz == 1) {
2047 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2052 /* save range so we can do auto-return etc. */
2054 current_audio_range = range;
2056 /* now start rolling at the right place */
2058 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2061 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2062 TransportStateChange ();
2066 Session::request_bounded_roll (framepos_t start, framepos_t end)
2068 AudioRange ar (start, end, 0);
2069 list<AudioRange> lar;
2072 request_play_range (&lar, true);
2076 Session::set_requested_return_frame (framepos_t return_to)
2078 _requested_return_frame = return_to;
2082 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2084 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2085 ev->target2_frame = start;
2090 Session::engine_halted ()
2094 /* there will be no more calls to process(), so
2095 we'd better clean up for ourselves, right now.
2097 but first, make sure the butler is out of
2105 realtime_stop (false, true);
2106 non_realtime_stop (false, 0, ignored);
2107 transport_sub_state = 0;
2109 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2110 TransportStateChange (); /* EMIT SIGNAL */
2115 Session::xrun_recovery ()
2119 Xrun (_transport_frame); /* EMIT SIGNAL */
2121 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2123 /* it didn't actually halt, but we need
2124 to handle things in the same way.
2132 Session::route_processors_changed (RouteProcessorChange c)
2134 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2138 if (c.type == RouteProcessorChange::MeterPointChange) {
2143 if (c.type == RouteProcessorChange::RealTimeChange) {
2148 update_latency_compensation ();
2155 Session::allow_auto_play (bool yn)
2157 auto_play_legal = yn;
2161 Session::maybe_stop (framepos_t limit)
2163 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2164 if (synced_to_engine () && config.get_jack_time_master ()) {
2165 _engine.transport_stop ();
2166 } else if (!synced_to_engine ()) {
2175 Session::send_mmc_locate (framepos_t t)
2181 if (!_engine.freewheeling()) {
2182 Timecode::Time time;
2183 timecode_time_subframes (t, time);
2184 send_immediate_mmc (MIDI::MachineControlCommand (time));
2188 /** Ask the transport to not send timecode until further notice. The suspension
2189 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2190 * should be checked by the caller to find out when.
2193 Session::request_suspend_timecode_transmission ()
2195 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2200 Session::request_resume_timecode_transmission ()
2202 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2207 Session::timecode_transmission_suspended () const
2209 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;