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/playlist.h"
47 #include "ardour/profile.h"
48 #include "ardour/scene_changer.h"
49 #include "ardour/session.h"
50 #include "ardour/slave.h"
51 #include "ardour/tempo.h"
52 #include "ardour/operations.h"
53 #include "ardour/vca.h"
54 #include "ardour/vca_manager.h"
59 using namespace ARDOUR;
63 Session::add_post_transport_work (PostTransportWork ptw)
65 PostTransportWork oldval;
66 PostTransportWork newval;
70 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
71 newval = PostTransportWork (oldval | ptw);
72 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
78 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
82 Session::request_sync_source (Slave* new_slave)
84 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
87 seamless = Config->get_seamless_loop ();
89 if (dynamic_cast<Engine_Slave*>(new_slave)) {
90 /* JACK cannot support seamless looping at present */
91 Config->set_seamless_loop (false);
93 /* reset to whatever the value was before we last switched slaves */
94 Config->set_seamless_loop (_was_seamless);
97 /* save value of seamless from before the switch */
98 _was_seamless = seamless;
100 ev->slave = new_slave;
101 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
106 Session::request_transport_speed (double speed, bool as_default)
108 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
109 ev->third_yes_or_no = as_default; // as_default
110 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
114 /** Request a new transport speed, but if the speed parameter is exactly zero then use
115 * a very small +ve value to prevent the transport actually stopping. This method should
116 * be used by callers who are varying transport speed but don't ever want to stop it.
119 Session::request_transport_speed_nonzero (double speed, bool as_default)
125 request_transport_speed (speed, as_default);
129 Session::request_stop (bool abort, bool clear_state)
131 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_sample(), 0.0, abort, clear_state);
132 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, audible %3 transport %4 abort = %1, clear state = %2\n", abort, clear_state, audible_sample(), _transport_sample));
137 Session::request_locate (samplepos_t target_sample, bool with_roll)
139 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_sample, 0, false);
140 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_sample));
145 Session::force_locate (samplepos_t target_sample, bool with_roll)
147 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_sample, 0, true);
148 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_sample));
153 Session::unset_preroll_record_trim ()
155 _preroll_record_trim_len = 0;
159 Session::request_preroll_record_trim (samplepos_t rec_in, samplecnt_t preroll)
161 if (actively_recording ()) {
164 unset_preroll_record_trim ();
166 config.set_punch_in (false);
167 config.set_punch_out (false);
169 samplepos_t pos = std::max ((samplepos_t)0, rec_in - preroll);
170 _preroll_record_trim_len = preroll;
171 maybe_enable_record ();
172 request_locate (pos, true);
173 set_requested_return_sample (rec_in);
177 Session::request_count_in_record ()
179 if (actively_recording ()) {
182 if (transport_rolling()) {
185 maybe_enable_record ();
186 _count_in_once = true;
187 request_transport_speed (1.0, true);
191 Session::request_play_loop (bool yn, bool change_transport_roll)
194 // don't attempt to loop when not using Internal Transport
195 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
200 Location *location = _locations->auto_loop_location();
203 if (location == 0 && yn) {
204 error << _("Cannot loop - no loop range defined")
209 if (change_transport_roll) {
210 if (transport_rolling()) {
211 /* start looping at current speed */
212 target_speed = transport_speed ();
214 /* currently stopped */
216 /* start looping at normal speed */
223 /* leave the speed alone */
224 target_speed = transport_speed ();
227 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
228 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
232 if (!change_transport_roll) {
233 if (!transport_rolling()) {
234 /* we're not changing transport state, but we do want
235 to set up position for the new loop. Don't
236 do this if we're rolling already.
238 request_locate (location->start(), false);
242 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
243 // request an immediate locate to refresh the tracks
244 // after disabling looping
245 request_locate (_transport_sample-1, false);
251 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
253 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
255 ev->audio_range = *range;
257 ev->audio_range.clear ();
259 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
264 Session::request_cancel_play_range ()
266 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
272 Session::solo_selection_active ()
274 if ( _soloSelection.empty() ) {
281 Session::solo_selection ( StripableList &list, bool new_state )
283 boost::shared_ptr<ControlList> solo_list (new ControlList);
284 boost::shared_ptr<ControlList> unsolo_list (new ControlList);
287 _soloSelection = list;
289 _soloSelection.clear();
291 boost::shared_ptr<RouteList> rl = get_routes();
293 for (ARDOUR::RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
295 if ( !(*i)->is_track() ) {
299 boost::shared_ptr<Stripable> s (*i);
301 bool found = (std::find(list.begin(), list.end(), s) != list.end());
302 if ( new_state && found ) {
304 solo_list->push_back (s->solo_control());
306 //must invalidate playlists on selected tracks, so only selected regions get heard
307 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (*i);
309 boost::shared_ptr<Playlist> playlist = track->playlist();
311 playlist->ContentsChanged();
315 unsolo_list->push_back (s->solo_control());
319 set_controls (solo_list, 1.0, Controllable::NoGroup);
320 set_controls (unsolo_list, 0.0, Controllable::NoGroup);
324 Session::realtime_stop (bool abort, bool clear_state)
326 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_sample));
327 PostTransportWork todo = PostTransportWork (0);
329 /* assume that when we start, we'll be moving forwards */
331 if (_transport_speed < 0.0f) {
332 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
333 _default_transport_speed = 1.0;
335 todo = PostTransportWork (todo | PostTransportStop);
340 boost::shared_ptr<RouteList> r = routes.reader ();
342 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
343 (*i)->realtime_handle_transport_stopped ();
346 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_sample));
348 /* the duration change is not guaranteed to have happened, but is likely */
350 todo = PostTransportWork (todo | PostTransportDuration);
353 todo = PostTransportWork (todo | PostTransportAbort);
357 todo = PostTransportWork (todo | PostTransportClearSubstate);
361 add_post_transport_work (todo);
364 _clear_event_type (SessionEvent::StopOnce);
365 _clear_event_type (SessionEvent::RangeStop);
366 _clear_event_type (SessionEvent::RangeLocate);
368 //clear our solo-selection, if there is one
369 if ( solo_selection_active() ) {
370 solo_selection ( _soloSelection, false );
373 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
374 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
376 if (clear_state && !Config->get_loop_is_mode()) {
380 reset_slave_state ();
382 _transport_speed = 0;
383 _target_transport_speed = 0;
386 g_atomic_int_set (&_playback_load, 100);
387 g_atomic_int_set (&_capture_load, 100);
389 if (config.get_use_video_sync()) {
390 waiting_for_sync_offset = true;
393 transport_sub_state = 0;
397 Session::realtime_locate ()
399 boost::shared_ptr<RouteList> r = routes.reader ();
400 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
401 (*i)->realtime_locate ();
406 Session::butler_transport_work ()
408 /* Note: this function executes in the butler thread context */
412 PostTransportWork ptw;
413 boost::shared_ptr<RouteList> r = routes.reader ();
416 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
418 ptw = post_transport_work();
420 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
423 if (ptw & PostTransportLocate) {
425 if (get_play_loop() && !Config->get_seamless_loop()) {
427 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
429 /* this locate might be happening while we are
432 * Non-seamless looping will require a locate (below) that
433 * will reset capture buffers and throw away data.
435 * Rather than first find all tracks and see if they
436 * have outstanding data, just do a flush anyway. It
437 * may be cheaper this way anyway, and is certainly
441 bool more_disk_io_to_do = false;
445 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
451 if (more_disk_io_to_do) {
460 if (ptw & PostTransportAdjustPlaybackBuffering) {
461 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
462 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
464 tr->adjust_playback_buffering ();
465 /* and refill those buffers ... */
467 (*i)->non_realtime_locate (_transport_sample);
469 VCAList v = _vca_manager->vcas ();
470 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
471 (*i)->non_realtime_locate (_transport_sample);
475 if (ptw & PostTransportAdjustCaptureBuffering) {
476 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
477 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
479 tr->adjust_capture_buffering ();
484 if (ptw & PostTransportCurveRealloc) {
485 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
486 (*i)->curve_reallocate();
490 if (ptw & PostTransportSpeed) {
491 non_realtime_set_speed ();
494 if (ptw & PostTransportReverse) {
497 cumulative_rf_motion = 0;
500 /* don't seek if locate will take care of that in non_realtime_stop() */
502 if (!(ptw & PostTransportLocate)) {
503 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
504 (*i)->non_realtime_locate (_transport_sample);
506 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
507 /* new request, stop seeking, and start again */
508 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
512 VCAList v = _vca_manager->vcas ();
513 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
514 (*i)->non_realtime_locate (_transport_sample);
519 if (ptw & PostTransportLocate) {
520 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
521 non_realtime_locate ();
524 if (ptw & PostTransportStop) {
525 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
527 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
532 if (ptw & PostTransportOverWrite) {
533 non_realtime_overwrite (on_entry, finished);
535 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
540 if (ptw & PostTransportAudition) {
541 non_realtime_set_audition ();
544 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
546 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_sample, _butler->transport_work_requested()));
550 Session::non_realtime_set_speed ()
552 boost::shared_ptr<RouteList> rl = routes.reader();
553 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
554 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
556 tr->non_realtime_speed_change ();
562 Session::non_realtime_overwrite (int on_entry, bool& finished)
564 boost::shared_ptr<RouteList> rl = routes.reader();
565 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
566 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
567 if (tr && tr->pending_overwrite ()) {
568 tr->overwrite_existing_buffers ();
570 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
579 Session::non_realtime_locate ()
581 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_sample));
583 if (Config->get_loop_is_mode() && get_play_loop()) {
585 Location *loc = _locations->auto_loop_location();
587 if (!loc || (_transport_sample < loc->start() || _transport_sample >= loc->end())) {
588 /* jumped out of loop range: stop tracks from looping,
589 but leave loop (mode) enabled.
591 set_track_loop (false);
593 } else if (loc && Config->get_seamless_loop() &&
594 ((loc->start() <= _transport_sample) ||
595 (loc->end() > _transport_sample) ) ) {
597 /* jumping to start of loop. This might have been done before but it is
598 * idempotent and cheap. Doing it here ensures that when we start playback
599 * outside the loop we still flip tracks into the magic seamless mode
602 set_track_loop (true);
605 set_track_loop (false);
610 /* no more looping .. should have been noticed elsewhere */
617 boost::shared_ptr<RouteList> rl = routes.reader();
620 gint sc = g_atomic_int_get (&_seek_counter);
621 tf = _transport_sample;
623 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
624 (*i)->non_realtime_locate (tf);
625 if (sc != g_atomic_int_get (&_seek_counter)) {
632 /* VCAs are quick to locate because they have no data (except
633 automation) associated with them. Don't bother with a
634 restart mechanism here, but do use the same transport sample
635 that the Routes used.
637 VCAList v = _vca_manager->vcas ();
638 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
639 (*i)->non_realtime_locate (tf);
643 _scene_changer->locate (_transport_sample);
645 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
646 rather than clearing them so that the RT thread has to spend time constructing
647 them (in Session::click).
652 #ifdef USE_TRACKS_CODE_FEATURES
654 Session::select_playhead_priority_target (samplepos_t& jump_to)
658 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
664 if (Profile->get_trx() && transport_rolling() ) {
665 // We're playing, so do nothing.
666 // Next stop will put us where we need to be.
670 /* Note that the order of checking each AutoReturnTarget flag defines
671 the priority each flag.
673 Ardour/Mixbus: Last Locate
678 Tracks: Range Selection
684 if (autoreturn & RangeSelectionStart) {
685 if (!_range_selection.empty()) {
686 jump_to = _range_selection.from;
688 if (transport_rolling ()) {
689 /* Range selection no longer exists, but we're playing,
690 so do nothing. Next stop will put us where
698 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
699 /* don't try to handle loop play when synced to JACK */
701 if (!synced_to_engine()) {
702 Location *location = _locations->auto_loop_location();
705 jump_to = location->start();
707 if (Config->get_seamless_loop()) {
708 /* need to get track buffers reloaded */
709 set_track_loop (true);
715 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
716 if (!_object_selection.empty()) {
717 jump_to = _object_selection.from;
721 if (jump_to < 0 && (autoreturn & LastLocate)) {
722 jump_to = _last_roll_location;
730 Session::select_playhead_priority_target (samplepos_t& jump_to)
732 if (config.get_external_sync() || !config.get_auto_return()) {
736 jump_to = _last_roll_location;
743 Session::follow_playhead_priority ()
747 if (select_playhead_priority_target (target)) {
748 request_locate (target);
753 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
759 PostTransportWork ptw = post_transport_work();
764 boost::shared_ptr<RouteList> rl = routes.reader();
765 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
766 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
767 if (tr && tr->get_captured_samples () != 0) {
773 /* stop and locate are merged here because they share a lot of common stuff */
776 now = localtime (&xnow);
779 auditioner->cancel_audition ();
782 cumulative_rf_motion = 0;
786 begin_reversible_command (Operations::capture);
787 _have_captured = true;
790 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
792 if (abort && did_record) {
793 /* no reason to save the session file when we remove sources
795 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
798 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
799 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
801 tr->transport_stopped_wallclock (*now, xnow, abort);
805 if (abort && did_record) {
806 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
809 boost::shared_ptr<RouteList> r = routes.reader ();
811 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
812 if (!(*i)->is_auditioner()) {
813 (*i)->set_pending_declick (0);
818 commit_reversible_command ();
819 /* increase take name */
820 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
821 string newname = config.get_take_name();
822 config.set_take_name(bump_name_number (newname));
826 if (_engine.running()) {
827 PostTransportWork ptw = post_transport_work ();
829 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
830 (*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate) || pending_locate_flush);
832 VCAList v = _vca_manager->vcas ();
833 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
834 (*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate) || pending_locate_flush);
837 update_latency_compensation ();
840 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
842 if (auto_return_enabled ||
843 (ptw & PostTransportLocate) ||
844 (_requested_return_sample >= 0) ||
845 synced_to_engine()) {
847 if (pending_locate_flush) {
848 flush_all_inserts ();
851 // rg: what is the logic behind this case?
852 // _requested_return_sample should be ignored when synced_to_engine/slaved.
853 // currently worked around in MTC_Slave by forcing _requested_return_sample to -1
855 if ((auto_return_enabled || synced_to_engine() || _requested_return_sample >= 0) &&
856 !(ptw & PostTransportLocate)) {
858 /* no explicit locate queued */
860 bool do_locate = false;
862 if (_requested_return_sample >= 0) {
864 /* explicit return request pre-queued in event list. overrides everything else */
866 _transport_sample = _requested_return_sample;
872 if (select_playhead_priority_target (jump_to)) {
874 _transport_sample = jump_to;
879 _transport_sample = _last_roll_location;
884 _requested_return_sample = -1;
887 _engine.transport_locate (_transport_sample);
894 unset_preroll_record_trim ();
896 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
899 if (ptw & PostTransportClearSubstate) {
901 if (!Config->get_loop_is_mode()) {
906 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
909 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
910 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
911 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
912 (*i)->non_realtime_locate (_transport_sample);
914 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
916 /* we will be back */
923 VCAList v = _vca_manager->vcas ();
924 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
925 (*i)->non_realtime_locate (_transport_sample);
931 /* don't bother with this stuff if we're disconnected from the engine,
932 because there will be no process callbacks to deliver stuff from
935 if (_engine.connected() && !_engine.freewheeling()) {
936 // need to queue this in the next RT cycle
937 _send_timecode_update = true;
939 if (!dynamic_cast<MTC_Slave*>(_slave)) {
940 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
942 /* This (::non_realtime_stop()) gets called by main
943 process thread, which will lead to confusion
944 when calling AsyncMIDIPort::write().
946 Something must be done. XXX
948 send_mmc_locate (_transport_sample);
952 if ((ptw & PostTransportLocate) && get_record_enabled()) {
953 /* This is scheduled by realtime_stop(), which is also done
954 * when a slave requests /locate/ for an initial sync.
955 * We can't hold up the slave for long with a save() here,
956 * without breaking its initial sync cycle.
958 * save state only if there's no slave or if it's not yet locked.
960 if (!_slave || !_slave->locked()) {
961 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
962 SaveSessionRequested (_current_snapshot_name);
967 /* always try to get rid of this */
969 remove_pending_capture_state ();
971 /* save the current state of things if appropriate */
973 if (did_record && !saved) {
974 SaveSessionRequested (_current_snapshot_name);
977 if (ptw & PostTransportStop) {
979 if (!Config->get_loop_is_mode()) {
984 PositionChanged (_transport_sample); /* EMIT SIGNAL */
985 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
986 TransportStateChange (); /* EMIT SIGNAL */
987 AutomationWatch::instance().transport_stop_automation_watches (_transport_sample);
989 /* and start it up again if relevant */
991 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
992 request_transport_speed (1.0);
995 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
996 around for next time.
998 pending_locate_roll = false;
1002 Session::check_declick_out ()
1004 bool locate_required = transport_sub_state & PendingLocate;
1006 /* this is called after a process() iteration. if PendingDeclickOut was set,
1007 it means that we were waiting to declick the output (which has just been
1008 done) before maybe doing something else. this is where we do that "something else".
1010 note: called from the audio thread.
1013 if (transport_sub_state & PendingDeclickOut) {
1015 if (locate_required) {
1016 start_locate (pending_locate_sample, pending_locate_roll, pending_locate_flush);
1017 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1019 if (!(transport_sub_state & StopPendingCapture)) {
1020 stop_transport (pending_abort);
1021 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
1025 } else if (transport_sub_state & PendingLoopDeclickOut) {
1026 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
1027 transport_sub_state &= ~PendingLoopDeclickOut;
1032 Session::unset_play_loop ()
1036 clear_events (SessionEvent::AutoLoop);
1037 clear_events (SessionEvent::AutoLoopDeclick);
1038 set_track_loop (false);
1041 if (Config->get_seamless_loop()) {
1042 /* likely need to flush track buffers: this will locate us to wherever we are */
1043 add_post_transport_work (PostTransportLocate);
1044 _butler->schedule_transport_work ();
1050 Session::set_track_loop (bool yn)
1052 Location* loc = _locations->auto_loop_location ();
1058 boost::shared_ptr<RouteList> rl = routes.reader ();
1060 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1061 if (*i && !(*i)->is_private_route()) {
1062 (*i)->set_loop (yn ? loc : 0);
1068 Session::set_play_loop (bool yn, double speed)
1070 /* Called from event-handling context */
1074 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1075 /* nothing to do, or can't change loop status while recording */
1079 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1080 warning << string_compose (
1081 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1082 "Recommend changing the configured options"), PROGRAM_NAME)
1090 have_looped = false;
1094 unset_play_range ();
1096 if (Config->get_seamless_loop()) {
1097 if (!Config->get_loop_is_mode()) {
1098 /* set all tracks to use internal looping */
1099 set_track_loop (true);
1101 /* we will do this in the locate to the start OR when we hit the end
1102 * of the loop for the first time
1106 /* set all tracks to NOT use internal looping */
1107 set_track_loop (false);
1110 /* Put the delick and loop events in into the event list. The declick event will
1111 cause a de-clicking fade-out just before the end of the loop, and it will also result
1112 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1117 auto_loop_declick_range (loc, dcp, dcl);
1118 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1119 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1121 /* if requested to roll, locate to start of loop and
1122 * roll but ONLY if we're not already rolling.
1124 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1127 if (Config->get_loop_is_mode()) {
1128 /* loop IS a transport mode: if already
1129 rolling, do not locate to loop start.
1131 if (!transport_rolling() && (speed != 0.0)) {
1132 start_locate (loc->start(), true, true, false, true);
1136 start_locate (loc->start(), true, true, false, true);
1146 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1147 TransportStateChange ();
1150 Session::flush_all_inserts ()
1152 boost::shared_ptr<RouteList> r = routes.reader ();
1154 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1155 (*i)->flush_processors ();
1160 Session::start_locate (samplepos_t target_sample, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1162 if (target_sample < 0) {
1163 error << _("Locate called for negative sample position - ignored") << endmsg;
1167 if (synced_to_engine()) {
1172 _slave->speed_and_position (sp, pos);
1174 if (target_sample != pos) {
1176 if (config.get_jack_time_master()) {
1177 /* actually locate now, since otherwise jack_timebase_callback
1178 will use the incorrect _transport_sample and report an old
1179 and incorrect time to Jack transport
1181 locate (target_sample, with_roll, with_flush, for_loop_enabled, force);
1184 /* tell JACK to change transport position, and we will
1185 follow along later in ::follow_slave()
1188 _engine.transport_locate (target_sample);
1190 if (sp != 1.0f && with_roll) {
1191 _engine.transport_start ();
1197 locate (target_sample, with_roll, with_flush, for_loop_enabled, force);
1202 Session::worst_latency_preroll () const
1204 return _worst_output_latency + _worst_input_latency;
1208 Session::micro_locate (samplecnt_t distance)
1210 boost::shared_ptr<RouteList> rl = routes.reader();
1211 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1212 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1213 if (tr && !tr->can_internal_playback_seek (distance)) {
1218 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1219 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1221 tr->internal_playback_seek (distance);
1225 _transport_sample += distance;
1229 /** @param with_mmc true to send a MMC locate command when the locate is done */
1231 Session::locate (samplepos_t target_sample, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1233 bool need_butler = false;
1235 /* Locates for seamless looping are fairly different from other
1236 * locates. They assume that the diskstream buffers for each track
1237 * already have the correct data in them, and thus there is no need to
1238 * actually tell the tracks to locate. What does need to be done,
1239 * though, is all the housekeeping that is associated with non-linear
1240 * changes in the value of _transport_sample.
1243 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1244 target_sample, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1246 if (!force && _transport_sample == target_sample && !loop_changing && !for_loop_enabled) {
1248 /* already at the desired position. Not forced to locate,
1249 the loop isn't changing, so unless we're told to
1250 start rolling also, there's nothing to do but
1251 tell the world where we are (again).
1255 set_transport_speed (1.0, 0, false);
1257 loop_changing = false;
1258 Located (); /* EMIT SIGNAL */
1262 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1263 /* Schedule a declick. We'll be called again when its done.
1264 We only do it this way for ordinary locates, not those
1265 due to **seamless** loops.
1268 if (!(transport_sub_state & PendingDeclickOut)) {
1269 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1270 pending_locate_sample = target_sample;
1271 pending_locate_roll = with_roll;
1272 pending_locate_flush = with_flush;
1273 cerr << "Declick scheduled ... back soon\n";
1278 cerr << "... now doing the actual locate\n";
1280 // Update Timecode time
1281 _transport_sample = target_sample;
1282 // Bump seek counter so that any in-process locate in the butler
1283 // thread(s?) can restart.
1284 g_atomic_int_inc (&_seek_counter);
1285 _last_roll_or_reversal_location = target_sample;
1286 _remaining_latency_preroll = worst_latency_preroll ();
1287 timecode_time(_transport_sample, transmitting_timecode_time); // XXX here?
1289 /* do "stopped" stuff if:
1291 * we are rolling AND
1292 * no autoplay in effect AND
1293 * we're not going to keep rolling after the locate AND
1294 * !(playing a loop with JACK sync)
1298 bool transport_was_stopped = !transport_rolling();
1300 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1301 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1302 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1303 transport_was_stopped = true;
1305 /* otherwise tell the world that we located */
1309 if (force || !for_loop_enabled || loop_changing) {
1311 PostTransportWork todo = PostTransportLocate;
1313 if (with_roll && transport_was_stopped) {
1314 todo = PostTransportWork (todo | PostTransportRoll);
1317 add_post_transport_work (todo);
1322 /* this is functionally what clear_clicks() does but with a tentative lock */
1324 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1326 if (clickm.locked()) {
1328 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1337 /* switch from input if we're going to roll */
1338 if (Config->get_monitoring_model() == HardwareMonitoring) {
1339 set_track_monitor_input_status (!config.get_auto_input());
1342 /* otherwise we're going to stop, so do the opposite */
1343 if (Config->get_monitoring_model() == HardwareMonitoring) {
1344 set_track_monitor_input_status (true);
1348 /* cancel looped playback if transport pos outside of loop range */
1351 Location* al = _locations->auto_loop_location();
1354 if (_transport_sample < al->start() || _transport_sample >= al->end()) {
1356 // located outside the loop: cancel looping directly, this is called from event handling context
1358 have_looped = false;
1360 if (!Config->get_loop_is_mode()) {
1361 set_play_loop (false, _transport_speed);
1363 if (Config->get_seamless_loop()) {
1364 /* this will make the non_realtime_locate() in the butler
1365 which then causes seek() in tracks actually do the right
1368 set_track_loop (false);
1372 } else if (_transport_sample == al->start()) {
1374 // located to start of loop - this is looping, basically
1378 if (_last_roll_location != al->start()) {
1379 /* didn't start at loop start - playback must have
1380 * started before loop since we've now hit the loop
1383 add_post_transport_work (PostTransportLocate);
1389 boost::shared_ptr<RouteList> rl = routes.reader();
1391 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1392 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1394 if (tr && tr->rec_enable_control()->get_value()) {
1395 // tell it we've looped, so it can deal with the record state
1396 tr->transport_looped (_transport_sample);
1401 TransportLooped(); // EMIT SIGNAL
1407 _butler->schedule_transport_work ();
1410 loop_changing = false;
1412 _send_timecode_update = true;
1415 send_mmc_locate (_transport_sample);
1418 _last_roll_location = _last_roll_or_reversal_location = _transport_sample;
1419 if (!synced_to_engine () || _transport_sample == _engine.transport_sample ()) {
1420 Located (); /* EMIT SIGNAL */
1424 /** Set the transport speed.
1425 * Called from the process thread.
1426 * @param speed New speed
1429 Session::set_transport_speed (double speed, samplepos_t destination_sample, bool abort, bool clear_state, bool as_default)
1431 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1432 speed, abort, clear_state, _transport_speed, _transport_sample, as_default));
1434 /* max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1435 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1439 speed = min (8.0, speed);
1440 } else if (speed < 0) {
1441 speed = max (-8.0, speed);
1444 double new_engine_speed = 1.0;
1446 new_engine_speed = fabs (speed);
1447 if (speed < 0) speed = -1;
1448 if (speed > 0) speed = 1;
1451 if (_transport_speed == speed && new_engine_speed == _engine_speed) {
1452 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1453 _default_transport_speed = 1.0;
1458 #if 0 // TODO pref: allow vari-speed recording
1459 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1460 /* no varispeed during recording */
1461 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, sample %2\n",
1462 _transport_speed, _transport_sample));
1467 _target_transport_speed = fabs(speed);
1468 _engine_speed = new_engine_speed;
1470 if (transport_rolling() && speed == 0.0) {
1472 /* we are rolling and we want to stop */
1474 if (Config->get_monitoring_model() == HardwareMonitoring) {
1475 set_track_monitor_input_status (true);
1478 if (synced_to_engine ()) {
1480 /* do this here because our response to the slave won't
1483 _play_range = false;
1484 _count_in_once = false;
1487 _engine.transport_stop ();
1489 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1491 if (!auto_return_enabled) {
1492 _requested_return_sample = destination_sample;
1495 stop_transport (abort);
1498 } else if (transport_stopped() && speed == 1.0) {
1500 _default_transport_speed = speed;
1502 /* we are stopped and we want to start rolling at speed 1 */
1504 if (Config->get_loop_is_mode() && play_loop) {
1506 Location *location = _locations->auto_loop_location();
1508 if (location != 0) {
1509 if (_transport_sample != location->start()) {
1511 if (Config->get_seamless_loop()) {
1512 /* force tracks to do their thing */
1513 set_track_loop (true);
1516 /* jump to start and then roll from there */
1518 request_locate (location->start(), true);
1524 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1525 set_track_monitor_input_status (false);
1528 if (synced_to_engine()) {
1529 _engine.transport_start ();
1530 _count_in_once = false;
1537 /* not zero, not 1.0 ... varispeed */
1539 // TODO handled transport start.. _remaining_latency_preroll
1540 // and reversal of playback direction.
1542 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1543 warning << string_compose (
1544 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1551 if (actively_recording()) {
1556 if (speed > 0.0 && _transport_sample == current_end_sample()) {
1560 if (speed < 0.0 && _transport_sample == 0) {
1566 /* if we are reversing relative to the current speed, or relative to the speed
1567 before the last stop, then we have to do extra work.
1570 PostTransportWork todo = PostTransportWork (0);
1572 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1573 todo = PostTransportWork (todo | PostTransportReverse);
1574 _last_roll_or_reversal_location = _transport_sample;
1577 _last_transport_speed = _transport_speed;
1578 _transport_speed = speed;
1581 _default_transport_speed = speed;
1585 add_post_transport_work (todo);
1586 _butler->schedule_transport_work ();
1589 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1591 /* throttle signal emissions.
1592 * when slaved [_last]_transport_speed
1593 * usually changes every cycle (tiny amounts due to DLL).
1594 * Emitting a signal every cycle is overkill and unwarranted.
1596 * Using _last_transport_speed is not acceptable,
1597 * since it allows for large changes over a long period
1598 * of time. Hence we introduce a dedicated variable to keep track
1600 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1601 * for TransportStateChange() here is the ShuttleControl display.
1603 if (fabs (_signalled_varispeed - actual_speed ()) > .002
1604 // still, signal hard changes to 1.0 and 0.0:
1605 || (actual_speed () == 1.0 && _signalled_varispeed != 1.0)
1606 || (actual_speed () == 0.0 && _signalled_varispeed != 0.0)
1609 TransportStateChange (); /* EMIT SIGNAL */
1610 _signalled_varispeed = actual_speed ();
1616 /** Stop the transport. */
1618 Session::stop_transport (bool abort, bool clear_state)
1620 _count_in_once = false;
1621 if (_transport_speed == 0.0f) {
1625 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1627 if (!get_transport_declick_required()) {
1629 /* stop has not yet been scheduled */
1631 boost::shared_ptr<RouteList> rl = routes.reader();
1632 samplepos_t stop_target = audible_sample();
1636 if (actively_recording() && /* we are recording */
1637 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1639 /* we need to capture the audio that is still somewhere in the pipeline between
1640 wherever it was generated and the process callback. This means that even though
1641 the user (or something else) has asked us to stop, we have to roll
1642 past this point and then reset the playhead/transport location to
1643 the position at which the stop was requested.
1645 we still need playback to "stop" now, however, which is why we schedule
1649 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1650 _transport_sample, _worst_input_latency,
1651 _transport_sample + _worst_input_latency,
1654 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1655 _transport_sample + _worst_input_latency,
1660 /* request a declick at the start of the next process cycle() so that playback ceases.
1661 It will remain silent until we actually stop (at the StopOnce event somewhere in
1662 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1663 does not stop the transport too early.
1665 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1669 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1671 new_bits = PendingDeclickOut;
1672 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_sample));
1675 /* we'll be called again after the declick */
1676 transport_sub_state = SubState (transport_sub_state|new_bits);
1677 pending_abort = abort;
1683 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1685 /* declick was scheduled, but we've been called again, which means it is really time to stop
1687 XXX: we should probably split this off into its own method and call it explicitly.
1690 realtime_stop (abort, clear_state);
1691 _butler->schedule_transport_work ();
1695 /** Called from the process thread */
1697 Session::start_transport ()
1699 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1701 _last_roll_location = _transport_sample;
1702 _last_roll_or_reversal_location = _transport_sample;
1703 _remaining_latency_preroll = worst_latency_preroll ();
1705 have_looped = false;
1707 /* if record status is Enabled, move it to Recording. if its
1708 already Recording, move it to Disabled.
1711 switch (record_status()) {
1713 if (!config.get_punch_in()) {
1714 /* This is only for UIs (keep blinking rec-en before
1715 * punch-in, don't show rec-region etc). The UI still
1716 * depends on SessionEvent::PunchIn and ensuing signals.
1718 * The disk-writers handle punch in/out internally
1719 * in their local delay-compensated timeframe.
1727 disable_record (false);
1735 transport_sub_state |= PendingDeclickIn;
1737 _transport_speed = _default_transport_speed;
1738 _target_transport_speed = _transport_speed;
1740 if (!_engine.freewheeling()) {
1741 Timecode::Time time;
1742 timecode_time_subframes (_transport_sample, time);
1743 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1744 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1747 if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
1748 _count_in_once = false;
1749 /* calculate count-in duration (in audio samples)
1750 * - use [fixed] tempo/meter at _transport_sample
1751 * - calc duration of 1 bar + time-to-beat before or at transport_sample
1753 const Tempo& tempo = _tempo_map->tempo_at_sample (_transport_sample);
1754 const Meter& meter = _tempo_map->meter_at_sample (_transport_sample);
1756 const double num = meter.divisions_per_bar ();
1757 const double den = meter.note_divisor ();
1758 const double barbeat = _tempo_map->exact_qn_at_sample (_transport_sample, 0) * den / (4. * num);
1759 const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
1761 _count_in_samples = meter.samples_per_bar (tempo, _current_sample_rate);
1763 double dt = _count_in_samples / num;
1764 if (bar_fract == 0) {
1765 /* at bar boundary, count-in 2 bars before start. */
1766 _count_in_samples *= 2;
1768 /* beats left after full bar until roll position */
1769 _count_in_samples *= 1. + bar_fract;
1772 if (_count_in_samples > _remaining_latency_preroll) {
1773 _remaining_latency_preroll = _count_in_samples;
1777 samplepos_t cf = _transport_sample - _count_in_samples;
1778 samplecnt_t offset = _click_io->connected_latency (true);
1779 while (cf < _transport_sample + offset) {
1780 add_click (cf, clickbeat == 0);
1782 clickbeat = fmod (clickbeat + 1, num);
1785 if (_count_in_samples < _remaining_latency_preroll) {
1786 _count_in_samples = _remaining_latency_preroll;
1791 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1792 TransportStateChange (); /* EMIT SIGNAL */
1795 /** Do any transport work in the audio thread that needs to be done after the
1796 * transport thread is finished. Audio thread, realtime safe.
1799 Session::post_transport ()
1801 PostTransportWork ptw = post_transport_work ();
1803 if (ptw & PostTransportAudition) {
1804 if (auditioner && auditioner->auditioning()) {
1805 process_function = &Session::process_audition;
1807 process_function = &Session::process_with_events;
1811 if (ptw & PostTransportStop) {
1813 transport_sub_state = 0;
1816 if (ptw & PostTransportLocate) {
1818 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1819 _count_in_once = false;
1822 transport_sub_state = 0;
1827 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1830 set_post_transport_work (PostTransportWork (0));
1834 Session::reset_rf_scale (samplecnt_t motion)
1836 cumulative_rf_motion += motion;
1838 if (cumulative_rf_motion < 4 * _current_sample_rate) {
1840 } else if (cumulative_rf_motion < 8 * _current_sample_rate) {
1842 } else if (cumulative_rf_motion < 16 * _current_sample_rate) {
1854 Session::mtc_status_changed (bool yn)
1856 g_atomic_int_set (&_mtc_active, yn);
1857 MTCSyncStateChanged( yn );
1861 Session::ltc_status_changed (bool yn)
1863 g_atomic_int_set (&_ltc_active, yn);
1864 LTCSyncStateChanged( yn );
1868 Session::use_sync_source (Slave* new_slave)
1870 /* Runs in process() context */
1872 bool non_rt_required = false;
1874 /* XXX this deletion is problematic because we're in RT context */
1880 /* slave change, reset any DiskIO block on disk output because it is no
1881 longer valid with a new slave.
1883 DiskReader::set_no_disk_output (false);
1885 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1887 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1888 MTCSyncStateChanged(mtc_slave->locked() );
1890 if (g_atomic_int_get (&_mtc_active) ){
1891 g_atomic_int_set (&_mtc_active, 0);
1892 MTCSyncStateChanged( false );
1894 mtc_status_connection.disconnect ();
1897 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1899 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1900 LTCSyncStateChanged (ltc_slave->locked() );
1902 if (g_atomic_int_get (&_ltc_active) ){
1903 g_atomic_int_set (&_ltc_active, 0);
1904 LTCSyncStateChanged( false );
1906 ltc_status_connection.disconnect ();
1909 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1911 // need to queue this for next process() cycle
1912 _send_timecode_update = true;
1914 boost::shared_ptr<RouteList> rl = routes.reader();
1915 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1916 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1917 if (tr && !tr->is_private_route()) {
1918 tr->set_slaved (_slave != 0);
1922 if (non_rt_required) {
1923 add_post_transport_work (PostTransportSpeed);
1924 _butler->schedule_transport_work ();
1931 Session::drop_sync_source ()
1933 request_sync_source (0);
1937 Session::switch_to_sync_source (SyncSource src)
1941 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1945 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1950 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1953 catch (failed_constructor& err) {
1959 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1964 new_slave = new LTC_Slave (*this);
1967 catch (failed_constructor& err) {
1974 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1979 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1982 catch (failed_constructor& err) {
1988 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1992 if (config.get_video_pullup() != 0.0f) {
1996 new_slave = new Engine_Slave (*AudioEngine::instance());
2004 request_sync_source (new_slave);
2008 Session::unset_play_range ()
2010 _play_range = false;
2011 _clear_event_type (SessionEvent::RangeStop);
2012 _clear_event_type (SessionEvent::RangeLocate);
2016 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
2020 /* Called from event-processing context */
2022 unset_play_range ();
2024 if (range.empty()) {
2025 /* _play_range set to false in unset_play_range()
2027 if (!leave_rolling) {
2028 /* stop transport */
2029 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
2037 /* cancel loop play */
2040 list<AudioRange>::size_type sz = range.size();
2044 list<AudioRange>::iterator i = range.begin();
2045 list<AudioRange>::iterator next;
2047 while (i != range.end()) {
2052 /* locating/stopping is subject to delays for declicking.
2055 samplepos_t requested_sample = i->end;
2057 if (requested_sample > current_block_size) {
2058 requested_sample -= current_block_size;
2060 requested_sample = 0;
2063 if (next == range.end()) {
2064 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_sample, 0, 0.0f);
2066 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_sample, (*next).start, 0.0f);
2074 } else if (sz == 1) {
2076 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2081 /* save range so we can do auto-return etc. */
2083 current_audio_range = range;
2085 /* now start rolling at the right place */
2087 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2090 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2091 TransportStateChange ();
2095 Session::request_bounded_roll (samplepos_t start, samplepos_t end)
2097 AudioRange ar (start, end, 0);
2098 list<AudioRange> lar;
2101 request_play_range (&lar, true);
2105 Session::set_requested_return_sample (samplepos_t return_to)
2107 _requested_return_sample = return_to;
2111 Session::request_roll_at_and_return (samplepos_t start, samplepos_t return_to)
2113 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2114 ev->target2_sample = start;
2119 Session::engine_halted ()
2123 /* there will be no more calls to process(), so
2124 we'd better clean up for ourselves, right now.
2126 but first, make sure the butler is out of
2134 realtime_stop (false, true);
2135 non_realtime_stop (false, 0, ignored);
2136 transport_sub_state = 0;
2138 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2139 TransportStateChange (); /* EMIT SIGNAL */
2144 Session::xrun_recovery ()
2148 Xrun (_transport_sample); /* EMIT SIGNAL */
2150 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2152 /* it didn't actually halt, but we need
2153 to handle things in the same way.
2161 Session::route_processors_changed (RouteProcessorChange c)
2163 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2167 if (c.type == RouteProcessorChange::MeterPointChange) {
2172 if (c.type == RouteProcessorChange::RealTimeChange) {
2177 update_latency_compensation ();
2184 Session::allow_auto_play (bool yn)
2186 auto_play_legal = yn;
2190 Session::maybe_stop (samplepos_t limit)
2192 if ((_transport_speed > 0.0f && _transport_sample >= limit) || (_transport_speed < 0.0f && _transport_sample == 0)) {
2193 if (synced_to_engine () && config.get_jack_time_master ()) {
2194 _engine.transport_stop ();
2195 } else if (!synced_to_engine ()) {
2204 Session::send_mmc_locate (samplepos_t t)
2210 if (!_engine.freewheeling()) {
2211 Timecode::Time time;
2212 timecode_time_subframes (t, time);
2213 send_immediate_mmc (MIDI::MachineControlCommand (time));
2217 /** Ask the transport to not send timecode until further notice. The suspension
2218 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2219 * should be checked by the caller to find out when.
2222 Session::request_suspend_timecode_transmission ()
2224 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2229 Session::request_resume_timecode_transmission ()
2231 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2236 Session::timecode_transmission_suspended () const
2238 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;