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.
26 #include "pbd/error.h"
27 #include "pbd/enumwriter.h"
28 #include "pbd/pthread_utils.h"
29 #include "pbd/memento_command.h"
31 #include "midi++/mmc.h"
32 #include "midi++/port.h"
33 #include "midi++/manager.h"
35 #include "ardour/ardour.h"
36 #include "ardour/audioengine.h"
37 #include "ardour/auditioner.h"
38 #include "ardour/butler.h"
39 #include "ardour/debug.h"
40 #include "ardour/location.h"
41 #include "ardour/session.h"
42 #include "ardour/slave.h"
43 #include "ardour/operations.h"
48 using namespace ARDOUR;
52 Session::add_post_transport_work (PostTransportWork ptw)
54 PostTransportWork oldval;
55 PostTransportWork newval;
59 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
60 newval = PostTransportWork (oldval | ptw);
61 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
67 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
71 Session::request_input_change_handling ()
73 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
74 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
80 Session::request_sync_source (Slave* new_slave)
82 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
85 seamless = Config->get_seamless_loop ();
87 if (dynamic_cast<JACK_Slave*>(new_slave)) {
88 /* JACK cannot support seamless looping at present */
89 Config->set_seamless_loop (false);
91 /* reset to whatever the value was before we last switched slaves */
92 Config->set_seamless_loop (_was_seamless);
95 /* save value of seamless from before the switch */
96 _was_seamless = seamless;
98 ev->slave = new_slave;
103 Session::request_transport_speed (double speed)
105 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
106 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
110 /** Request a new transport speed, but if the speed parameter is exactly zero then use
111 * a very small +ve value to prevent the transport actually stopping. This method should
112 * be used by callers who are varying transport speed but don't ever want to stop it.
115 Session::request_transport_speed_nonzero (double speed)
121 request_transport_speed (speed);
125 Session::request_track_speed (Track* tr, double speed)
127 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
133 Session::request_stop (bool abort, bool clear_state)
135 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
136 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
141 Session::request_locate (framepos_t target_frame, bool with_roll)
143 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
144 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
149 Session::force_locate (framepos_t target_frame, bool with_roll)
151 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
152 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
157 Session::request_play_loop (bool yn, bool leave_rolling)
160 Location *location = _locations->auto_loop_location();
162 if (location == 0 && yn) {
163 error << _("Cannot loop - no loop range defined")
168 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
169 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
172 if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
173 // request an immediate locate to refresh the tracks
174 // after disabling looping
175 request_locate (_transport_frame-1, false);
180 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
182 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
184 ev->audio_range = *range;
186 ev->audio_range.clear ();
188 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
193 Session::realtime_stop (bool abort, bool clear_state)
195 DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
196 PostTransportWork todo = PostTransportWork (0);
198 /* assume that when we start, we'll be moving forwards */
200 if (_transport_speed < 0.0f) {
201 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
203 todo = PostTransportWork (todo | PostTransportStop);
208 boost::shared_ptr<RouteList> r = routes.reader ();
210 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
211 (*i)->realtime_handle_transport_stopped ();
214 if (actively_recording()) {
216 /* move the transport position back to where the
217 request for a stop was noticed. we rolled
218 past that point to pick up delayed input (and/or to delick)
221 if (_worst_output_latency > current_block_size) {
222 /* we rolled past the stop point to pick up data that had
223 not yet arrived. move back to where the stop occured.
225 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
227 decrement_transport_position (current_block_size);
230 /* the duration change is not guaranteed to have happened, but is likely */
232 todo = PostTransportWork (todo | PostTransportDuration);
236 todo = PostTransportWork (todo | PostTransportAbort);
240 todo = PostTransportWork (todo | PostTransportClearSubstate);
244 add_post_transport_work (todo);
247 _clear_event_type (SessionEvent::StopOnce);
248 _clear_event_type (SessionEvent::RangeStop);
249 _clear_event_type (SessionEvent::RangeLocate);
251 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
252 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
254 reset_slave_state ();
256 _transport_speed = 0;
257 _target_transport_speed = 0;
259 g_atomic_int_set (&_playback_load, 100);
260 g_atomic_int_set (&_capture_load, 100);
262 if (config.get_use_video_sync()) {
263 waiting_for_sync_offset = true;
266 transport_sub_state = 0;
270 Session::butler_transport_work ()
274 PostTransportWork ptw;
275 boost::shared_ptr<RouteList> r = routes.reader ();
277 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
279 ptw = post_transport_work();
281 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
283 if (ptw & PostTransportAdjustPlaybackBuffering) {
284 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
285 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
287 tr->adjust_playback_buffering ();
288 /* and refill those buffers ... */
289 tr->non_realtime_locate (_transport_frame);
295 if (ptw & PostTransportAdjustCaptureBuffering) {
296 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
297 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
299 tr->adjust_capture_buffering ();
304 if (ptw & PostTransportCurveRealloc) {
305 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
306 (*i)->curve_reallocate();
310 if (ptw & PostTransportInputChange) {
311 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
312 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
314 tr->non_realtime_input_change ();
319 if (ptw & PostTransportSpeed) {
320 non_realtime_set_speed ();
323 if (ptw & PostTransportReverse) {
326 cumulative_rf_motion = 0;
329 /* don't seek if locate will take care of that in non_realtime_stop() */
331 if (!(ptw & PostTransportLocate)) {
333 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
334 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
335 if (tr && !tr->hidden()) {
336 tr->non_realtime_locate (_transport_frame);
338 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
339 /* new request, stop seeking, and start again */
340 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
347 if (ptw & PostTransportLocate) {
348 non_realtime_locate ();
351 if (ptw & PostTransportStop) {
352 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
354 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
359 if (ptw & PostTransportOverWrite) {
360 non_realtime_overwrite (on_entry, finished);
362 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
367 if (ptw & PostTransportAudition) {
368 non_realtime_set_audition ();
371 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
373 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
377 Session::non_realtime_set_speed ()
379 boost::shared_ptr<RouteList> rl = routes.reader();
380 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
381 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
383 tr->non_realtime_set_speed ();
389 Session::non_realtime_overwrite (int on_entry, bool& finished)
391 boost::shared_ptr<RouteList> rl = routes.reader();
392 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
393 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
394 if (tr && tr->pending_overwrite ()) {
395 tr->overwrite_existing_buffers ();
397 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
406 Session::non_realtime_locate ()
408 boost::shared_ptr<RouteList> rl = routes.reader();
409 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
410 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
412 tr->non_realtime_locate (_transport_frame);
419 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
425 PostTransportWork ptw = post_transport_work();
430 boost::shared_ptr<RouteList> rl = routes.reader();
431 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
432 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
433 if (tr && tr->get_captured_frames () != 0) {
439 /* stop and locate are merged here because they share a lot of common stuff */
442 now = localtime (&xnow);
445 auditioner->cancel_audition ();
449 cumulative_rf_motion = 0;
453 begin_reversible_command (Operations::capture);
454 _have_captured = true;
457 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
459 if (abort && did_record) {
460 /* no reason to save the session file when we remove sources
462 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
465 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
466 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
468 tr->transport_stopped_wallclock (*now, xnow, abort);
472 if (abort && did_record) {
473 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
476 boost::shared_ptr<RouteList> r = routes.reader ();
478 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
479 if (!(*i)->is_hidden()) {
480 (*i)->set_pending_declick (0);
485 commit_reversible_command ();
488 if (_engine.running()) {
489 update_latency_compensation (true, abort);
492 bool const auto_return_enabled =
493 (!config.get_external_sync() && config.get_auto_return());
495 if (auto_return_enabled ||
496 (ptw & PostTransportLocate) ||
497 (_requested_return_frame >= 0) ||
500 if (pending_locate_flush) {
501 flush_all_inserts ();
504 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
505 !(ptw & PostTransportLocate)) {
507 /* no explicit locate queued */
509 bool do_locate = false;
511 if (_requested_return_frame >= 0) {
513 /* explicit return request pre-queued in event list. overrides everything else */
515 cerr << "explicit auto-return to " << _requested_return_frame << endl;
517 _transport_frame = _requested_return_frame;
521 if (config.get_auto_return()) {
525 /* don't try to handle loop play when synced to JACK */
527 if (!synced_to_jack()) {
529 Location *location = _locations->auto_loop_location();
532 _transport_frame = location->start();
534 _transport_frame = _last_roll_location;
539 } else if (_play_range) {
541 /* return to start of range */
543 if (!current_audio_range.empty()) {
544 _transport_frame = current_audio_range.front().start;
550 /* regular auto-return */
552 _transport_frame = _last_roll_location;
558 _requested_return_frame = -1;
561 _engine.transport_locate (_transport_frame);
567 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
570 if (ptw & PostTransportClearSubstate) {
575 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
577 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
578 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
579 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
580 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
581 if (tr && !tr->hidden()) {
582 tr->non_realtime_locate (_transport_frame);
585 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
587 /* we will be back */
594 send_full_time_code (_transport_frame);
596 if (!dynamic_cast<MTC_Slave*>(_slave)) {
597 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
598 send_mmc_locate (_transport_frame);
601 if ((ptw & PostTransportLocate) && get_record_enabled()) {
602 /* capture start has been changed, so save pending state */
603 save_state ("", true);
607 /* always try to get rid of this */
609 remove_pending_capture_state ();
611 /* save the current state of things if appropriate */
613 if (did_record && !saved) {
614 save_state (_current_snapshot_name);
617 if (ptw & PostTransportStop) {
622 PositionChanged (_transport_frame); /* EMIT SIGNAL */
623 TransportStateChange (); /* EMIT SIGNAL */
625 /* and start it up again if relevant */
627 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
628 request_transport_speed (1.0);
629 pending_locate_roll = false;
634 Session::check_declick_out ()
636 bool locate_required = transport_sub_state & PendingLocate;
638 /* this is called after a process() iteration. if PendingDeclickOut was set,
639 it means that we were waiting to declick the output (which has just been
640 done) before doing something else. this is where we do that "something else".
642 note: called from the audio thread.
645 if (transport_sub_state & PendingDeclickOut) {
647 if (locate_required) {
648 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
649 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
651 stop_transport (pending_abort);
652 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
658 Session::unset_play_loop ()
661 clear_events (SessionEvent::AutoLoop);
663 // set all tracks to NOT use internal looping
664 boost::shared_ptr<RouteList> rl = routes.reader ();
665 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
666 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
667 if (tr && !tr->hidden()) {
674 Session::set_play_loop (bool yn)
676 /* Called from event-handling context */
680 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
681 /* nothing to do, or can't change loop status while recording */
685 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
686 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
687 "Recommend changing the configured options"), PROGRAM_NAME)
700 if (Config->get_seamless_loop()) {
701 // set all tracks to use internal looping
702 boost::shared_ptr<RouteList> rl = routes.reader ();
703 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
704 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
705 if (tr && !tr->hidden()) {
711 // set all tracks to NOT use internal looping
712 boost::shared_ptr<RouteList> rl = routes.reader ();
713 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
714 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
715 if (tr && !tr->hidden()) {
721 /* put the loop event into the event list */
723 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
726 /* locate to start of loop and roll. If doing seamless loop, force a
727 locate+buffer refill even if we are positioned there already.
730 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
738 TransportStateChange ();
741 Session::flush_all_inserts ()
743 boost::shared_ptr<RouteList> r = routes.reader ();
745 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
746 (*i)->flush_processors ();
751 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
753 if (synced_to_jack()) {
758 _slave->speed_and_position (sp, pos);
760 if (target_frame != pos) {
762 /* tell JACK to change transport position, and we will
763 follow along later in ::follow_slave()
766 _engine.transport_locate (target_frame);
768 if (sp != 1.0f && with_roll) {
769 _engine.transport_start ();
775 locate (target_frame, with_roll, with_flush, with_loop, force);
780 Session::micro_locate (framecnt_t distance)
782 boost::shared_ptr<RouteList> rl = routes.reader();
783 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
784 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
785 if (tr && !tr->can_internal_playback_seek (distance)) {
790 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
791 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
793 tr->internal_playback_seek (distance);
797 _transport_frame += distance;
801 /** @param with_mmc true to send a MMC locate command when the locate is done */
803 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
805 if (actively_recording() && !with_loop) {
809 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
811 set_transport_speed (1.0, false);
813 loop_changing = false;
814 Located (); /* EMIT SIGNAL */
818 // Update Timecode time
819 // [DR] FIXME: find out exactly where this should go below
820 _transport_frame = target_frame;
821 timecode_time(_transport_frame, transmitting_timecode_time);
822 outbound_mtc_timecode_frame = _transport_frame;
823 next_quarter_frame_to_send = 0;
825 if (_transport_speed && (!with_loop || loop_changing)) {
826 /* schedule a declick. we'll be called again when its done */
828 if (!(transport_sub_state & PendingDeclickOut)) {
829 transport_sub_state |= (PendingDeclickOut|PendingLocate);
830 pending_locate_frame = target_frame;
831 pending_locate_roll = with_roll;
832 pending_locate_flush = with_flush;
837 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
838 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
841 if (force || !with_loop || loop_changing) {
843 PostTransportWork todo = PostTransportLocate;
846 todo = PostTransportWork (todo | PostTransportRoll);
849 add_post_transport_work (todo);
850 _butler->schedule_transport_work ();
854 /* this is functionally what clear_clicks() does but with a tentative lock */
856 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
858 if (clickm.locked()) {
860 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
869 /* switch from input if we're going to roll */
870 if (Config->get_monitoring_model() == HardwareMonitoring) {
872 boost::shared_ptr<RouteList> rl = routes.reader();
873 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
874 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
875 if (tr && tr->record_enabled ()) {
876 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
877 tr->monitor_input (!config.get_auto_input());
882 /* otherwise we're going to stop, so do the opposite */
883 if (Config->get_monitoring_model() == HardwareMonitoring) {
885 boost::shared_ptr<RouteList> rl = routes.reader();
886 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
887 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
888 if (tr && tr->record_enabled ()) {
889 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
890 tr->monitor_input (true);
896 /* cancel looped playback if transport pos outside of loop range */
898 Location* al = _locations->auto_loop_location();
900 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
901 // cancel looping directly, this is called from event handling context
902 set_play_loop (false);
904 else if (al && _transport_frame == al->start()) {
906 // this is only necessary for seamless looping
908 boost::shared_ptr<RouteList> rl = routes.reader();
909 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
910 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
911 if (tr && tr->record_enabled ()) {
912 // tell it we've looped, so it can deal with the record state
913 tr->transport_looped(_transport_frame);
918 TransportLooped(); // EMIT SIGNAL
922 loop_changing = false;
924 _send_timecode_update = true;
927 send_mmc_locate (_transport_frame);
930 Located (); /* EMIT SIGNAL */
933 /** Set the transport speed.
934 * @param speed New speed
938 Session::set_transport_speed (double speed, bool abort, bool clear_state)
940 DEBUG_TRACE (DEBUG::Transport, string_compose ("Set transport speed to %1, abort = %2 clear_state = %3, current = %4\n", speed, abort, clear_state, _transport_speed));
942 if (_transport_speed == speed) {
946 _target_transport_speed = fabs(speed);
948 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
949 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
953 speed = min (8.0, speed);
954 } else if (speed < 0) {
955 speed = max (-8.0, speed);
958 if (transport_rolling() && speed == 0.0) {
960 /* we are rolling and we want to stop */
962 if (Config->get_monitoring_model() == HardwareMonitoring)
964 boost::shared_ptr<RouteList> rl = routes.reader();
966 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
967 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
968 if (tr && tr->record_enabled ()) {
969 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
970 tr->monitor_input (true);
975 if (synced_to_jack ()) {
977 /* do this here because our response to the slave won't
983 _engine.transport_stop ();
985 stop_transport (abort);
990 } else if (transport_stopped() && speed == 1.0) {
992 /* we are stopped and we want to start rolling at speed 1 */
994 if (Config->get_monitoring_model() == HardwareMonitoring) {
996 boost::shared_ptr<RouteList> rl = routes.reader();
997 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
998 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
999 if (config.get_auto_input() && tr && tr->record_enabled ()) {
1000 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
1001 tr->monitor_input (false);
1006 if (synced_to_jack()) {
1007 _engine.transport_start ();
1014 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
1015 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1021 if (actively_recording()) {
1025 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1029 if (speed < 0.0 && _transport_frame == 0) {
1035 /* if we are reversing relative to the current speed, or relative to the speed
1036 before the last stop, then we have to do extra work.
1039 PostTransportWork todo = PostTransportWork (0);
1041 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1042 todo = PostTransportWork (todo | PostTransportReverse);
1043 _last_roll_or_reversal_location = _transport_frame;
1046 _last_transport_speed = _transport_speed;
1047 _transport_speed = speed;
1049 boost::shared_ptr<RouteList> rl = routes.reader();
1050 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1051 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1052 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1053 todo = PostTransportWork (todo | PostTransportSpeed);
1058 add_post_transport_work (todo);
1059 _butler->schedule_transport_work ();
1065 /** Stop the transport. */
1067 Session::stop_transport (bool abort, bool clear_state)
1069 if (_transport_speed == 0.0f) {
1073 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1075 boost::shared_ptr<RouteList> rl = routes.reader();
1076 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1077 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1079 tr->prepare_to_stop (_transport_frame);
1083 /* we need to capture the audio that has still not yet been received by the system
1084 at the time the stop is requested, so we have to roll past that time.
1086 we want to declick before stopping, so schedule the autostop for one
1087 block before the actual end. we'll declick in the subsequent block,
1088 and then we'll really be stopped.
1091 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1092 _transport_frame + _worst_output_latency - current_block_size,
1096 transport_sub_state |= StopPendingCapture;
1097 pending_abort = abort;
1102 if ((transport_sub_state & PendingDeclickOut) == 0) {
1104 if (!(transport_sub_state & StopPendingCapture)) {
1105 boost::shared_ptr<RouteList> rl = routes.reader();
1106 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1107 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1109 tr->prepare_to_stop (_transport_frame);
1114 transport_sub_state |= PendingDeclickOut;
1115 /* we'll be called again after the declick */
1116 pending_abort = abort;
1120 realtime_stop (abort, clear_state);
1121 _butler->schedule_transport_work ();
1125 Session::start_transport ()
1127 _last_roll_location = _transport_frame;
1128 _last_roll_or_reversal_location = _transport_frame;
1130 have_looped = false;
1132 /* if record status is Enabled, move it to Recording. if its
1133 already Recording, move it to Disabled.
1136 switch (record_status()) {
1138 if (!config.get_punch_in()) {
1145 disable_record (false);
1153 transport_sub_state |= PendingDeclickIn;
1155 _transport_speed = 1.0;
1156 _target_transport_speed = 1.0;
1158 boost::shared_ptr<RouteList> rl = routes.reader();
1159 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1160 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1162 tr->realtime_set_speed (tr->speed(), true);
1164 (*i)->automation_snapshot (_transport_frame, true);
1167 Timecode::Time time;
1168 timecode_time_subframes (_transport_frame, time);
1169 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1170 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1173 TransportStateChange (); /* EMIT SIGNAL */
1176 /** Do any transport work in the audio thread that needs to be done after the
1177 * transport thread is finished. Audio thread, realtime safe.
1180 Session::post_transport ()
1182 PostTransportWork ptw = post_transport_work ();
1184 if (ptw & PostTransportAudition) {
1185 if (auditioner && auditioner->auditioning()) {
1186 process_function = &Session::process_audition;
1188 process_function = &Session::process_with_events;
1192 if (ptw & PostTransportStop) {
1194 transport_sub_state = 0;
1197 if (ptw & PostTransportLocate) {
1199 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1203 transport_sub_state = 0;
1208 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1211 set_post_transport_work (PostTransportWork (0));
1215 Session::reset_rf_scale (framecnt_t motion)
1217 cumulative_rf_motion += motion;
1219 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1221 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1223 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1235 Session::use_sync_source (Slave* new_slave)
1237 /* Runs in process() context */
1239 bool non_rt_required = false;
1241 /* XXX this deletion is problematic because we're in RT context */
1246 boost::shared_ptr<RouteList> rl = routes.reader();
1247 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1248 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1249 if (tr && !tr->hidden()) {
1250 if (tr->realtime_set_speed (tr->speed(), true)) {
1251 non_rt_required = true;
1253 tr->set_slaved (_slave != 0);
1257 if (non_rt_required) {
1258 add_post_transport_work (PostTransportSpeed);
1259 _butler->schedule_transport_work ();
1266 Session::drop_sync_source ()
1268 request_sync_source (0);
1272 Session::switch_to_sync_source (SyncSource src)
1276 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1280 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1285 new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
1288 catch (failed_constructor& err) {
1294 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1299 new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
1302 catch (failed_constructor& err) {
1308 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1312 if (config.get_video_pullup() != 0.0f) {
1316 new_slave = new JACK_Slave (_engine.jack());
1324 request_sync_source (new_slave);
1328 Session::reverse_track_buffers ()
1330 add_post_transport_work (PostTransportReverse);
1331 _butler->schedule_transport_work ();
1335 Session::set_track_speed (Track* track, double speed)
1337 if (track->realtime_set_speed (speed, false)) {
1338 add_post_transport_work (PostTransportSpeed);
1339 _butler->schedule_transport_work ();
1345 Session::unset_play_range ()
1347 _play_range = false;
1348 _clear_event_type (SessionEvent::RangeStop);
1349 _clear_event_type (SessionEvent::RangeLocate);
1353 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1357 /* Called from event-processing context */
1359 unset_play_range ();
1361 if (range.empty()) {
1362 /* _play_range set to false in unset_play_range()
1364 if (!leave_rolling) {
1365 /* stop transport */
1366 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1374 /* cancel loop play */
1377 list<AudioRange>::size_type sz = range.size();
1381 list<AudioRange>::iterator i = range.begin();
1382 list<AudioRange>::iterator next;
1384 while (i != range.end()) {
1389 /* locating/stopping is subject to delays for declicking.
1392 framepos_t requested_frame = i->end;
1394 if (requested_frame > current_block_size) {
1395 requested_frame -= current_block_size;
1397 requested_frame = 0;
1400 if (next == range.end()) {
1401 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1403 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1411 } else if (sz == 1) {
1413 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1418 /* save range so we can do auto-return etc. */
1420 current_audio_range = range;
1422 /* now start rolling at the right place */
1424 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1427 TransportStateChange ();
1431 Session::request_bounded_roll (framepos_t start, framepos_t end)
1433 AudioRange ar (start, end, 0);
1434 list<AudioRange> lar;
1437 request_play_range (&lar, true);
1440 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1442 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1443 ev->target2_frame = start;
1448 Session::engine_halted ()
1452 /* there will be no more calls to process(), so
1453 we'd better clean up for ourselves, right now.
1455 but first, make sure the butler is out of
1459 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1460 set_post_transport_work (PostTransportWork (0));
1463 realtime_stop (false, true);
1464 non_realtime_stop (false, 0, ignored);
1465 transport_sub_state = 0;
1467 TransportStateChange (); /* EMIT SIGNAL */
1472 Session::xrun_recovery ()
1474 Xrun (_transport_frame); //EMIT SIGNAL
1476 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1478 /* it didn't actually halt, but we need
1479 to handle things in the same way.
1487 Session::route_processors_changed (RouteProcessorChange c)
1489 if (c.type == RouteProcessorChange::MeterPointChange) {
1493 update_latency_compensation (false, false);
1498 Session::update_latency_compensation (bool with_stop, bool abort)
1500 bool update_jack = false;
1501 PostTransportWork ptw;
1503 if (_state_of_the_state & Deletion) {
1507 _worst_track_latency = 0;
1508 ptw = post_transport_work();
1510 #undef DEBUG_LATENCY
1511 #ifdef DEBUG_LATENCY
1512 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1515 boost::shared_ptr<RouteList> r = routes.reader ();
1517 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1520 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1523 framecnt_t old_latency = (*i)->output()->signal_latency ();
1524 framecnt_t track_latency = (*i)->update_total_latency ();
1526 if (old_latency != track_latency) {
1527 (*i)->input()->update_port_total_latencies ();
1528 (*i)->output()->update_port_total_latencies ();
1532 if (!(*i)->is_hidden() && ((*i)->active())) {
1533 _worst_track_latency = max (_worst_track_latency, track_latency);
1538 _engine.update_total_latencies ();
1541 #ifdef DEBUG_LATENCY
1542 cerr << "\tworst was " << _worst_track_latency << endl;
1545 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1546 (*i)->set_latency_delay (_worst_track_latency);
1549 set_worst_io_latencies ();
1551 /* reflect any changes in latencies into capture offsets
1554 boost::shared_ptr<RouteList> rl = routes.reader();
1555 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1556 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1558 tr->set_capture_offset ();
1564 Session::allow_auto_play (bool yn)
1566 auto_play_legal = yn;
1570 Session::reset_jack_connection (jack_client_t* jack)
1574 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1575 js->reset_client (jack);
1580 Session::maybe_stop (framepos_t limit)
1582 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1583 if (synced_to_jack () && config.get_jack_time_master ()) {
1584 _engine.transport_stop ();
1585 } else if (!synced_to_jack ()) {
1594 Session::send_mmc_locate (framepos_t t)
1596 Timecode::Time time;
1597 timecode_time_subframes (t, time);
1598 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
1601 /** Ask the transport to not send timecode until further notice. The suspension
1602 * will come into effect some finite time after this call, and timecode_transmission_suspended()
1603 * should be checked by the caller to find out when.
1606 Session::request_suspend_timecode_transmission ()
1608 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1613 Session::request_resume_timecode_transmission ()
1615 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1620 Session::timecode_transmission_suspended () const
1622 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;