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 ();
589 boost::shared_ptr<RouteList> rl = routes.reader();
592 const framepos_t tf = _transport_frame;
594 cerr << "\n\n >>> START Non-RT locate on routes to " << tf << "\n\n";
596 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
597 (*i)->non_realtime_locate (_transport_frame);
598 if (tf != _transport_frame) {
599 /* new locate request arrived while processing
600 this one. start over.
602 cerr << "\n\n\n\n RESTART LOCATE @ " << _transport_frame << endl;
607 cerr << "\n\n <<< DONE Non-RT locate on routes\n\n";
611 VCAList v = _vca_manager->vcas ();
612 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
613 (*i)->non_realtime_locate (_transport_frame);
617 microseconds_t end = get_microseconds ();
618 cerr << "Locate took " << setprecision (3) << ((end - begin) /1000000.0) << " secs\n";
620 _scene_changer->locate (_transport_frame);
622 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
623 rather than clearing them so that the RT thread has to spend time constructing
624 them (in Session::click).
629 #ifdef USE_TRACKS_CODE_FEATURES
631 Session::select_playhead_priority_target (framepos_t& jump_to)
635 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
641 if (Profile->get_trx() && transport_rolling() ) {
642 // We're playing, so do nothing.
643 // Next stop will put us where we need to be.
647 /* Note that the order of checking each AutoReturnTarget flag defines
648 the priority each flag.
650 Ardour/Mixbus: Last Locate
655 Tracks: Range Selection
661 if (autoreturn & RangeSelectionStart) {
662 if (!_range_selection.empty()) {
663 jump_to = _range_selection.from;
665 if (transport_rolling ()) {
666 /* Range selection no longer exists, but we're playing,
667 so do nothing. Next stop will put us where
675 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
676 /* don't try to handle loop play when synced to JACK */
678 if (!synced_to_engine()) {
679 Location *location = _locations->auto_loop_location();
682 jump_to = location->start();
684 if (Config->get_seamless_loop()) {
685 /* need to get track buffers reloaded */
686 set_track_loop (true);
692 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
693 if (!_object_selection.empty()) {
694 jump_to = _object_selection.from;
698 if (jump_to < 0 && (autoreturn & LastLocate)) {
699 jump_to = _last_roll_location;
707 Session::select_playhead_priority_target (framepos_t& jump_to)
709 if (config.get_external_sync() || !config.get_auto_return()) {
713 jump_to = _last_roll_location;
720 Session::follow_playhead_priority ()
724 if (select_playhead_priority_target (target)) {
725 request_locate (target);
730 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
736 PostTransportWork ptw = post_transport_work();
741 boost::shared_ptr<RouteList> rl = routes.reader();
742 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
743 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
744 if (tr && tr->get_captured_frames () != 0) {
750 /* stop and locate are merged here because they share a lot of common stuff */
753 now = localtime (&xnow);
756 auditioner->cancel_audition ();
759 cumulative_rf_motion = 0;
763 begin_reversible_command (Operations::capture);
764 _have_captured = true;
767 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
769 if (abort && did_record) {
770 /* no reason to save the session file when we remove sources
772 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
775 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
776 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
778 tr->transport_stopped_wallclock (*now, xnow, abort);
782 if (abort && did_record) {
783 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
786 boost::shared_ptr<RouteList> r = routes.reader ();
788 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
789 if (!(*i)->is_auditioner()) {
790 (*i)->set_pending_declick (0);
795 commit_reversible_command ();
796 /* increase take name */
797 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
798 string newname = config.get_take_name();
799 config.set_take_name(bump_name_number (newname));
803 if (_engine.running()) {
804 PostTransportWork ptw = post_transport_work ();
806 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
807 (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
809 VCAList v = _vca_manager->vcas ();
810 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
811 (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
814 update_latency_compensation ();
817 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
819 if (auto_return_enabled ||
820 (ptw & PostTransportLocate) ||
821 (_requested_return_frame >= 0) ||
822 synced_to_engine()) {
824 if (pending_locate_flush) {
825 flush_all_inserts ();
828 // rg: what is the logic behind this case?
829 // _requested_return_frame should be ignored when synced_to_engine/slaved.
830 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
832 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
833 !(ptw & PostTransportLocate)) {
835 /* no explicit locate queued */
837 bool do_locate = false;
839 if (_requested_return_frame >= 0) {
841 /* explicit return request pre-queued in event list. overrides everything else */
843 _transport_frame = _requested_return_frame;
849 if (select_playhead_priority_target (jump_to)) {
851 _transport_frame = jump_to;
856 _transport_frame = _last_roll_location;
861 _requested_return_frame = -1;
864 _engine.transport_locate (_transport_frame);
871 unset_preroll_record_trim ();
873 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
876 if (ptw & PostTransportClearSubstate) {
878 if (!Config->get_loop_is_mode()) {
883 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
886 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
887 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
888 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
889 (*i)->non_realtime_locate (_transport_frame);
891 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
893 /* we will be back */
900 VCAList v = _vca_manager->vcas ();
901 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
902 (*i)->non_realtime_locate (_transport_frame);
908 /* don't bother with this stuff if we're disconnected from the engine,
909 because there will be no process callbacks to deliver stuff from
912 if (_engine.connected() && !_engine.freewheeling()) {
913 // need to queue this in the next RT cycle
914 _send_timecode_update = true;
916 if (!dynamic_cast<MTC_Slave*>(_slave)) {
917 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
919 /* This (::non_realtime_stop()) gets called by main
920 process thread, which will lead to confusion
921 when calling AsyncMIDIPort::write().
923 Something must be done. XXX
925 send_mmc_locate (_transport_frame);
929 if ((ptw & PostTransportLocate) && get_record_enabled()) {
930 /* This is scheduled by realtime_stop(), which is also done
931 * when a slave requests /locate/ for an initial sync.
932 * We can't hold up the slave for long with a save() here,
933 * without breaking its initial sync cycle.
935 * save state only if there's no slave or if it's not yet locked.
937 if (!_slave || !_slave->locked()) {
938 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
939 SaveSessionRequested (_current_snapshot_name);
944 /* always try to get rid of this */
946 remove_pending_capture_state ();
948 /* save the current state of things if appropriate */
950 if (did_record && !saved) {
951 SaveSessionRequested (_current_snapshot_name);
954 if (ptw & PostTransportStop) {
956 if (!Config->get_loop_is_mode()) {
961 PositionChanged (_transport_frame); /* EMIT SIGNAL */
962 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
963 TransportStateChange (); /* EMIT SIGNAL */
964 AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
966 /* and start it up again if relevant */
968 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
969 request_transport_speed (1.0);
972 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
973 around for next time.
975 pending_locate_roll = false;
979 Session::check_declick_out ()
981 bool locate_required = transport_sub_state & PendingLocate;
983 /* this is called after a process() iteration. if PendingDeclickOut was set,
984 it means that we were waiting to declick the output (which has just been
985 done) before maybe doing something else. this is where we do that "something else".
987 note: called from the audio thread.
990 if (transport_sub_state & PendingDeclickOut) {
992 if (locate_required) {
993 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
994 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
996 if (!(transport_sub_state & StopPendingCapture)) {
997 stop_transport (pending_abort);
998 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1002 } else if (transport_sub_state & PendingLoopDeclickOut) {
1003 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
1004 transport_sub_state &= ~PendingLoopDeclickOut;
1009 Session::unset_play_loop ()
1013 clear_events (SessionEvent::AutoLoop);
1014 clear_events (SessionEvent::AutoLoopDeclick);
1015 set_track_loop (false);
1018 if (Config->get_seamless_loop()) {
1019 /* likely need to flush track buffers: this will locate us to wherever we are */
1020 add_post_transport_work (PostTransportLocate);
1021 _butler->schedule_transport_work ();
1027 Session::set_track_loop (bool yn)
1029 Location* loc = _locations->auto_loop_location ();
1035 boost::shared_ptr<RouteList> rl = routes.reader ();
1037 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1038 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1039 if (tr && !tr->is_private_route()) {
1040 tr->set_loop (yn ? loc : 0);
1046 Session::set_play_loop (bool yn, double speed)
1048 /* Called from event-handling context */
1052 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1053 /* nothing to do, or can't change loop status while recording */
1057 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1058 warning << string_compose (
1059 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1060 "Recommend changing the configured options"), PROGRAM_NAME)
1068 have_looped = false;
1072 unset_play_range ();
1074 if (Config->get_seamless_loop()) {
1075 if (!Config->get_loop_is_mode()) {
1076 /* set all tracks to use internal looping */
1077 set_track_loop (true);
1079 /* we will do this in the locate to the start OR when we hit the end
1080 * of the loop for the first time
1084 /* set all tracks to NOT use internal looping */
1085 set_track_loop (false);
1088 /* Put the delick and loop events in into the event list. The declick event will
1089 cause a de-clicking fade-out just before the end of the loop, and it will also result
1090 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1095 auto_loop_declick_range (loc, dcp, dcl);
1096 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1097 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1099 /* if requested to roll, locate to start of loop and
1100 * roll but ONLY if we're not already rolling.
1102 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1105 if (Config->get_loop_is_mode()) {
1106 /* loop IS a transport mode: if already
1107 rolling, do not locate to loop start.
1109 if (!transport_rolling() && (speed != 0.0)) {
1110 start_locate (loc->start(), true, true, false, true);
1114 start_locate (loc->start(), true, true, false, true);
1124 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1125 TransportStateChange ();
1128 Session::flush_all_inserts ()
1130 boost::shared_ptr<RouteList> r = routes.reader ();
1132 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1133 (*i)->flush_processors ();
1138 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1140 if (target_frame < 0) {
1141 error << _("Locate called for negative sample position - ignored") << endmsg;
1145 if (synced_to_engine()) {
1150 _slave->speed_and_position (sp, pos);
1152 if (target_frame != pos) {
1154 if (config.get_jack_time_master()) {
1155 /* actually locate now, since otherwise jack_timebase_callback
1156 will use the incorrect _transport_frame and report an old
1157 and incorrect time to Jack transport
1159 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1162 /* tell JACK to change transport position, and we will
1163 follow along later in ::follow_slave()
1166 _engine.transport_locate (target_frame);
1168 if (sp != 1.0f && with_roll) {
1169 _engine.transport_start ();
1175 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1180 Session::micro_locate (framecnt_t distance)
1182 boost::shared_ptr<RouteList> rl = routes.reader();
1183 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1184 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1185 if (tr && !tr->can_internal_playback_seek (distance)) {
1190 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1191 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1193 tr->internal_playback_seek (distance);
1197 _transport_frame += distance;
1201 /** @param with_mmc true to send a MMC locate command when the locate is done */
1203 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1205 bool need_butler = false;
1207 /* Locates for seamless looping are fairly different from other
1208 * locates. They assume that the diskstream buffers for each track
1209 * already have the correct data in them, and thus there is no need to
1210 * actually tell the tracks to locate. What does need to be done,
1211 * though, is all the housekeeping that is associated with non-linear
1212 * changes in the value of _transport_frame.
1215 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1216 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1218 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1220 /* already at the desired position. Not forced to locate,
1221 the loop isn't changing, so unless we're told to
1222 start rolling also, there's nothing to do but
1223 tell the world where we are (again).
1227 set_transport_speed (1.0, 0, false);
1229 loop_changing = false;
1230 Located (); /* EMIT SIGNAL */
1234 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1235 /* Schedule a declick. We'll be called again when its done.
1236 We only do it this way for ordinary locates, not those
1237 due to **seamless** loops.
1240 if (!(transport_sub_state & PendingDeclickOut)) {
1241 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1242 pending_locate_frame = target_frame;
1243 pending_locate_roll = with_roll;
1244 pending_locate_flush = with_flush;
1249 // Update Timecode time
1250 _transport_frame = target_frame;
1251 _last_roll_or_reversal_location = target_frame;
1252 timecode_time(_transport_frame, transmitting_timecode_time);
1254 /* do "stopped" stuff if:
1256 * we are rolling AND
1257 * no autoplay in effect AND
1258 * we're not going to keep rolling after the locate AND
1259 * !(playing a loop with JACK sync)
1263 bool transport_was_stopped = !transport_rolling();
1265 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1266 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1267 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1268 transport_was_stopped = true;
1270 /* otherwise tell the world that we located */
1274 if (force || !for_loop_enabled || loop_changing) {
1276 PostTransportWork todo = PostTransportLocate;
1278 if (with_roll && transport_was_stopped) {
1279 todo = PostTransportWork (todo | PostTransportRoll);
1282 add_post_transport_work (todo);
1287 /* this is functionally what clear_clicks() does but with a tentative lock */
1289 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1291 if (clickm.locked()) {
1293 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1302 /* switch from input if we're going to roll */
1303 if (Config->get_monitoring_model() == HardwareMonitoring) {
1304 set_track_monitor_input_status (!config.get_auto_input());
1307 /* otherwise we're going to stop, so do the opposite */
1308 if (Config->get_monitoring_model() == HardwareMonitoring) {
1309 set_track_monitor_input_status (true);
1313 /* cancel looped playback if transport pos outside of loop range */
1316 Location* al = _locations->auto_loop_location();
1319 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1321 // located outside the loop: cancel looping directly, this is called from event handling context
1323 have_looped = false;
1325 if (!Config->get_loop_is_mode()) {
1326 set_play_loop (false, _transport_speed);
1328 if (Config->get_seamless_loop()) {
1329 /* this will make the non_realtime_locate() in the butler
1330 which then causes seek() in tracks actually do the right
1333 set_track_loop (false);
1337 } else if (_transport_frame == al->start()) {
1339 // located to start of loop - this is looping, basically
1343 if (_last_roll_location != al->start()) {
1344 /* didn't start at loop start - playback must have
1345 * started before loop since we've now hit the loop
1348 add_post_transport_work (PostTransportLocate);
1354 boost::shared_ptr<RouteList> rl = routes.reader();
1356 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1357 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1359 if (tr && tr->rec_enable_control()->get_value()) {
1360 // tell it we've looped, so it can deal with the record state
1361 tr->transport_looped (_transport_frame);
1366 TransportLooped(); // EMIT SIGNAL
1372 _butler->schedule_transport_work ();
1375 loop_changing = false;
1377 _send_timecode_update = true;
1380 send_mmc_locate (_transport_frame);
1383 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1384 if (!synced_to_engine () || _transport_frame == _engine.transport_frame ()) {
1385 Located (); /* EMIT SIGNAL */
1389 /** Set the transport speed.
1390 * Called from the process thread.
1391 * @param speed New speed
1394 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1396 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1397 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1399 if (_transport_speed == speed) {
1400 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1401 _default_transport_speed = 1.0;
1406 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1407 /* no varispeed during recording */
1408 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1409 _transport_speed, _transport_frame));
1413 _target_transport_speed = fabs(speed);
1415 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1416 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1420 speed = min (8.0, speed);
1421 } else if (speed < 0) {
1422 speed = max (-8.0, speed);
1425 if (transport_rolling() && speed == 0.0) {
1427 /* we are rolling and we want to stop */
1429 if (Config->get_monitoring_model() == HardwareMonitoring) {
1430 set_track_monitor_input_status (true);
1433 if (synced_to_engine ()) {
1435 /* do this here because our response to the slave won't
1438 _play_range = false;
1439 _count_in_once = false;
1442 _engine.transport_stop ();
1444 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1446 if (!auto_return_enabled) {
1447 _requested_return_frame = destination_frame;
1450 stop_transport (abort);
1453 } else if (transport_stopped() && speed == 1.0) {
1455 _default_transport_speed = speed;
1457 /* we are stopped and we want to start rolling at speed 1 */
1459 if (Config->get_loop_is_mode() && play_loop) {
1461 Location *location = _locations->auto_loop_location();
1463 if (location != 0) {
1464 if (_transport_frame != location->start()) {
1466 if (Config->get_seamless_loop()) {
1467 /* force tracks to do their thing */
1468 set_track_loop (true);
1471 /* jump to start and then roll from there */
1473 request_locate (location->start(), true);
1479 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1480 set_track_monitor_input_status (false);
1483 if (synced_to_engine()) {
1484 _engine.transport_start ();
1485 _count_in_once = false;
1492 /* not zero, not 1.0 ... varispeed */
1494 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1495 warning << string_compose (
1496 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1502 if (actively_recording()) {
1506 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1510 if (speed < 0.0 && _transport_frame == 0) {
1516 /* if we are reversing relative to the current speed, or relative to the speed
1517 before the last stop, then we have to do extra work.
1520 PostTransportWork todo = PostTransportWork (0);
1522 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1523 todo = PostTransportWork (todo | PostTransportReverse);
1524 _last_roll_or_reversal_location = _transport_frame;
1527 _last_transport_speed = _transport_speed;
1528 _transport_speed = speed;
1531 _default_transport_speed = speed;
1534 boost::shared_ptr<RouteList> rl = routes.reader();
1535 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1536 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1537 if (tr && tr->realtime_speed_change()) {
1538 todo = PostTransportWork (todo | PostTransportSpeed);
1543 add_post_transport_work (todo);
1544 _butler->schedule_transport_work ();
1547 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1549 /* throttle signal emissions.
1550 * when slaved [_last]_transport_speed
1551 * usually changes every cycle (tiny amounts due to DLL).
1552 * Emitting a signal every cycle is overkill and unwarranted.
1554 * Using _last_transport_speed is not acceptable,
1555 * since it allows for large changes over a long period
1556 * of time. Hence we introduce a dedicated variable to keep track
1558 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1559 * for TransportStateChange() here is the ShuttleControl display.
1561 if (fabs (_signalled_varispeed - speed) > .002
1562 // still, signal hard changes to 1.0 and 0.0:
1563 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1564 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1567 TransportStateChange (); /* EMIT SIGNAL */
1568 _signalled_varispeed = speed;
1574 /** Stop the transport. */
1576 Session::stop_transport (bool abort, bool clear_state)
1578 _count_in_once = false;
1579 if (_transport_speed == 0.0f) {
1583 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1585 if (!get_transport_declick_required()) {
1587 /* stop has not yet been scheduled */
1589 boost::shared_ptr<RouteList> rl = routes.reader();
1590 framepos_t stop_target = audible_frame();
1592 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1593 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1595 tr->prepare_to_stop (_transport_frame, stop_target);
1601 if (actively_recording() && /* we are recording */
1602 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1604 /* we need to capture the audio that is still somewhere in the pipeline between
1605 wherever it was generated and the process callback. This means that even though
1606 the user (or something else) has asked us to stop, we have to roll
1607 past this point and then reset the playhead/transport location to
1608 the position at which the stop was requested.
1610 we still need playback to "stop" now, however, which is why we schedule
1614 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1615 _transport_frame, _worst_input_latency,
1616 _transport_frame + _worst_input_latency,
1619 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1620 _transport_frame + _worst_input_latency,
1625 /* request a declick at the start of the next process cycle() so that playback ceases.
1626 It will remain silent until we actually stop (at the StopOnce event somewhere in
1627 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1628 does not stop the transport too early.
1630 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1634 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1636 new_bits = PendingDeclickOut;
1637 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1640 /* we'll be called again after the declick */
1641 transport_sub_state = SubState (transport_sub_state|new_bits);
1642 pending_abort = abort;
1648 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1650 /* declick was scheduled, but we've been called again, which means it is really time to stop
1652 XXX: we should probably split this off into its own method and call it explicitly.
1655 realtime_stop (abort, clear_state);
1656 _butler->schedule_transport_work ();
1660 /** Called from the process thread */
1662 Session::start_transport ()
1664 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1666 _last_roll_location = _transport_frame;
1667 _last_roll_or_reversal_location = _transport_frame;
1669 have_looped = false;
1671 /* if record status is Enabled, move it to Recording. if its
1672 already Recording, move it to Disabled.
1675 switch (record_status()) {
1677 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1684 disable_record (false);
1692 transport_sub_state |= PendingDeclickIn;
1694 _transport_speed = _default_transport_speed;
1695 _target_transport_speed = _transport_speed;
1697 boost::shared_ptr<RouteList> rl = routes.reader();
1698 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1699 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1701 tr->realtime_speed_change ();
1705 if (!_engine.freewheeling()) {
1706 Timecode::Time time;
1707 timecode_time_subframes (_transport_frame, time);
1708 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1709 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1712 if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
1713 _count_in_once = false;
1714 /* calculate count-in duration (in audio samples)
1715 * - use [fixed] tempo/meter at _transport_frame
1716 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1718 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1719 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1721 const double num = meter.divisions_per_bar ();
1722 const double den = meter.note_divisor ();
1723 const double barbeat = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * den / (4. * num);
1724 const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
1726 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1728 double dt = _count_in_samples / num;
1729 if (bar_fract == 0) {
1730 /* at bar boundary, count-in 2 bars before start. */
1731 _count_in_samples *= 2;
1733 /* beats left after full bar until roll position */
1734 _count_in_samples *= 1. + bar_fract;
1738 framepos_t cf = _transport_frame - _count_in_samples;
1739 while (cf < _transport_frame) {
1740 add_click (cf - _worst_track_latency, clickbeat == 0);
1742 clickbeat = fmod (clickbeat + 1, num);
1747 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1748 TransportStateChange (); /* EMIT SIGNAL */
1751 /** Do any transport work in the audio thread that needs to be done after the
1752 * transport thread is finished. Audio thread, realtime safe.
1755 Session::post_transport ()
1757 PostTransportWork ptw = post_transport_work ();
1759 if (ptw & PostTransportAudition) {
1760 if (auditioner && auditioner->auditioning()) {
1761 process_function = &Session::process_audition;
1763 process_function = &Session::process_with_events;
1767 if (ptw & PostTransportStop) {
1769 transport_sub_state = 0;
1772 if (ptw & PostTransportLocate) {
1774 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1775 _count_in_once = false;
1778 transport_sub_state = 0;
1783 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1786 set_post_transport_work (PostTransportWork (0));
1790 Session::reset_rf_scale (framecnt_t motion)
1792 cumulative_rf_motion += motion;
1794 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1796 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1798 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1810 Session::mtc_status_changed (bool yn)
1812 g_atomic_int_set (&_mtc_active, yn);
1813 MTCSyncStateChanged( yn );
1817 Session::ltc_status_changed (bool yn)
1819 g_atomic_int_set (&_ltc_active, yn);
1820 LTCSyncStateChanged( yn );
1824 Session::use_sync_source (Slave* new_slave)
1826 /* Runs in process() context */
1828 bool non_rt_required = false;
1830 /* XXX this deletion is problematic because we're in RT context */
1836 /* slave change, reset any DiskIO block on disk output because it is no
1837 longer valid with a new slave.
1839 DiskReader::set_no_disk_output (false);
1841 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1843 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1844 MTCSyncStateChanged(mtc_slave->locked() );
1846 if (g_atomic_int_get (&_mtc_active) ){
1847 g_atomic_int_set (&_mtc_active, 0);
1848 MTCSyncStateChanged( false );
1850 mtc_status_connection.disconnect ();
1853 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1855 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1856 LTCSyncStateChanged (ltc_slave->locked() );
1858 if (g_atomic_int_get (&_ltc_active) ){
1859 g_atomic_int_set (&_ltc_active, 0);
1860 LTCSyncStateChanged( false );
1862 ltc_status_connection.disconnect ();
1865 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1867 // need to queue this for next process() cycle
1868 _send_timecode_update = true;
1870 boost::shared_ptr<RouteList> rl = routes.reader();
1871 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1872 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1873 if (tr && !tr->is_private_route()) {
1874 if (tr->realtime_speed_change()) {
1875 non_rt_required = true;
1877 tr->set_slaved (_slave != 0);
1881 if (non_rt_required) {
1882 add_post_transport_work (PostTransportSpeed);
1883 _butler->schedule_transport_work ();
1890 Session::drop_sync_source ()
1892 request_sync_source (0);
1896 Session::switch_to_sync_source (SyncSource src)
1900 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1904 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1909 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1912 catch (failed_constructor& err) {
1918 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1923 new_slave = new LTC_Slave (*this);
1926 catch (failed_constructor& err) {
1933 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1938 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1941 catch (failed_constructor& err) {
1947 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1951 if (config.get_video_pullup() != 0.0f) {
1955 new_slave = new Engine_Slave (*AudioEngine::instance());
1963 request_sync_source (new_slave);
1967 Session::unset_play_range ()
1969 _play_range = false;
1970 _clear_event_type (SessionEvent::RangeStop);
1971 _clear_event_type (SessionEvent::RangeLocate);
1975 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1979 /* Called from event-processing context */
1981 unset_play_range ();
1983 if (range.empty()) {
1984 /* _play_range set to false in unset_play_range()
1986 if (!leave_rolling) {
1987 /* stop transport */
1988 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1996 /* cancel loop play */
1999 list<AudioRange>::size_type sz = range.size();
2003 list<AudioRange>::iterator i = range.begin();
2004 list<AudioRange>::iterator next;
2006 while (i != range.end()) {
2011 /* locating/stopping is subject to delays for declicking.
2014 framepos_t requested_frame = i->end;
2016 if (requested_frame > current_block_size) {
2017 requested_frame -= current_block_size;
2019 requested_frame = 0;
2022 if (next == range.end()) {
2023 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
2025 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2033 } else if (sz == 1) {
2035 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2040 /* save range so we can do auto-return etc. */
2042 current_audio_range = range;
2044 /* now start rolling at the right place */
2046 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2049 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2050 TransportStateChange ();
2054 Session::request_bounded_roll (framepos_t start, framepos_t end)
2056 AudioRange ar (start, end, 0);
2057 list<AudioRange> lar;
2060 request_play_range (&lar, true);
2064 Session::set_requested_return_frame (framepos_t return_to)
2066 _requested_return_frame = return_to;
2070 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2072 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2073 ev->target2_frame = start;
2078 Session::engine_halted ()
2082 /* there will be no more calls to process(), so
2083 we'd better clean up for ourselves, right now.
2085 but first, make sure the butler is out of
2093 realtime_stop (false, true);
2094 non_realtime_stop (false, 0, ignored);
2095 transport_sub_state = 0;
2097 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2098 TransportStateChange (); /* EMIT SIGNAL */
2103 Session::xrun_recovery ()
2107 Xrun (_transport_frame); /* EMIT SIGNAL */
2109 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2111 /* it didn't actually halt, but we need
2112 to handle things in the same way.
2120 Session::route_processors_changed (RouteProcessorChange c)
2122 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2126 if (c.type == RouteProcessorChange::MeterPointChange) {
2131 if (c.type == RouteProcessorChange::RealTimeChange) {
2136 update_latency_compensation ();
2143 Session::allow_auto_play (bool yn)
2145 auto_play_legal = yn;
2149 Session::maybe_stop (framepos_t limit)
2151 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2152 if (synced_to_engine () && config.get_jack_time_master ()) {
2153 _engine.transport_stop ();
2154 } else if (!synced_to_engine ()) {
2163 Session::send_mmc_locate (framepos_t t)
2169 if (!_engine.freewheeling()) {
2170 Timecode::Time time;
2171 timecode_time_subframes (t, time);
2172 send_immediate_mmc (MIDI::MachineControlCommand (time));
2176 /** Ask the transport to not send timecode until further notice. The suspension
2177 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2178 * should be checked by the caller to find out when.
2181 Session::request_suspend_timecode_transmission ()
2183 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2188 Session::request_resume_timecode_transmission ()
2190 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2195 Session::timecode_transmission_suspended () const
2197 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;