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"
34 #include "ardour/ardour.h"
35 #include "ardour/audioengine.h"
36 #include "ardour/auditioner.h"
37 #include "ardour/butler.h"
38 #include "ardour/debug.h"
39 #include "ardour/location.h"
40 #include "ardour/session.h"
41 #include "ardour/slave.h"
46 using namespace ARDOUR;
50 Session::add_post_transport_work (PostTransportWork ptw)
52 PostTransportWork oldval;
53 PostTransportWork newval;
57 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
58 newval = PostTransportWork (oldval | ptw);
59 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
65 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
69 Session::request_input_change_handling ()
71 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
72 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
78 Session::request_sync_source (Slave* new_slave)
80 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
83 seamless = Config->get_seamless_loop ();
85 if (dynamic_cast<JACK_Slave*>(new_slave)) {
86 /* JACK cannot support seamless looping at present */
87 Config->set_seamless_loop (false);
89 /* reset to whatever the value was before we last switched slaves */
90 Config->set_seamless_loop (_was_seamless);
93 /* save value of seamless from before the switch */
94 _was_seamless = seamless;
96 ev->slave = new_slave;
101 Session::request_transport_speed (double speed)
103 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
104 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
109 Session::request_track_speed (Track* tr, double speed)
111 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
117 Session::request_stop (bool abort, bool clear_state)
119 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
120 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
125 Session::request_locate (nframes_t target_frame, bool with_roll)
127 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
128 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
133 Session::force_locate (nframes64_t target_frame, bool with_roll)
135 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
136 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
141 Session::request_play_loop (bool yn, bool leave_rolling)
144 Location *location = _locations.auto_loop_location();
146 if (location == 0 && yn) {
147 error << _("Cannot loop - no loop range defined")
152 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
153 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
156 if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
157 // request an immediate locate to refresh the tracks
158 // after disabling looping
159 request_locate (_transport_frame-1, false);
164 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
166 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
168 ev->audio_range = *range;
170 ev->audio_range.clear ();
172 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
177 Session::realtime_stop (bool abort, bool clear_state)
179 DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
180 PostTransportWork todo = PostTransportWork (0);
182 /* assume that when we start, we'll be moving forwards */
184 // FIXME: where should this really be? [DR]
185 //send_full_time_code();
186 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
187 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
189 if (_transport_speed < 0.0f) {
190 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
192 todo = PostTransportWork (todo | PostTransportStop);
195 if (actively_recording()) {
197 /* move the transport position back to where the
198 request for a stop was noticed. we rolled
199 past that point to pick up delayed input (and/or to delick)
202 if (_worst_output_latency > current_block_size) {
203 /* we rolled past the stop point to pick up data that had
204 not yet arrived. move back to where the stop occured.
206 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
208 decrement_transport_position (current_block_size);
211 /* the duration change is not guaranteed to have happened, but is likely */
213 todo = PostTransportWork (todo | PostTransportDuration);
217 todo = PostTransportWork (todo | PostTransportAbort);
221 todo = PostTransportWork (todo | PostTransportClearSubstate);
225 add_post_transport_work (todo);
228 _clear_event_type (SessionEvent::StopOnce);
229 _clear_event_type (SessionEvent::RangeStop);
230 _clear_event_type (SessionEvent::RangeLocate);
232 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
233 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
235 reset_slave_state ();
237 _transport_speed = 0;
238 _target_transport_speed = 0;
240 g_atomic_int_set (&_playback_load, 100);
241 g_atomic_int_set (&_capture_load, 100);
243 if (config.get_use_video_sync()) {
244 waiting_for_sync_offset = true;
247 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
251 Session::butler_transport_work ()
255 PostTransportWork ptw;
256 boost::shared_ptr<RouteList> r = routes.reader ();
258 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
260 ptw = post_transport_work();
262 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
264 if (ptw & PostTransportAdjustPlaybackBuffering) {
265 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
266 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
268 tr->adjust_playback_buffering ();
269 /* and refill those buffers ... */
270 tr->non_realtime_locate (_transport_frame);
276 if (ptw & PostTransportAdjustCaptureBuffering) {
277 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
278 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
280 tr->adjust_capture_buffering ();
285 if (ptw & PostTransportCurveRealloc) {
286 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
287 (*i)->curve_reallocate();
291 if (ptw & PostTransportInputChange) {
292 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
293 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
295 tr->non_realtime_input_change ();
300 if (ptw & PostTransportSpeed) {
301 non_realtime_set_speed ();
304 if (ptw & PostTransportReverse) {
307 cumulative_rf_motion = 0;
310 /* don't seek if locate will take care of that in non_realtime_stop() */
312 if (!(ptw & PostTransportLocate)) {
314 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
315 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
316 if (tr && !tr->hidden()) {
317 tr->non_realtime_locate (_transport_frame);
319 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
320 /* new request, stop seeking, and start again */
321 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
328 if (ptw & PostTransportLocate) {
329 non_realtime_locate ();
332 if (ptw & PostTransportStop) {
333 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
335 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
340 if (ptw & PostTransportOverWrite) {
341 non_realtime_overwrite (on_entry, finished);
343 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
348 if (ptw & PostTransportAudition) {
349 non_realtime_set_audition ();
352 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
354 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
358 Session::non_realtime_set_speed ()
360 boost::shared_ptr<RouteList> rl = routes.reader();
361 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
362 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
364 tr->non_realtime_set_speed ();
370 Session::non_realtime_overwrite (int on_entry, bool& finished)
372 boost::shared_ptr<RouteList> rl = routes.reader();
373 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
374 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
375 if (tr && tr->pending_overwrite ()) {
376 tr->overwrite_existing_buffers ();
378 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
387 Session::non_realtime_locate ()
389 boost::shared_ptr<RouteList> rl = routes.reader();
390 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
391 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
393 tr->non_realtime_locate (_transport_frame);
400 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
406 PostTransportWork ptw = post_transport_work();
411 boost::shared_ptr<RouteList> rl = routes.reader();
412 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
413 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
414 if (tr && tr->get_captured_frames () != 0) {
420 /* stop and locate are merged here because they share a lot of common stuff */
423 now = localtime (&xnow);
426 auditioner->cancel_audition ();
430 cumulative_rf_motion = 0;
434 begin_reversible_command ("capture");
435 _have_captured = true;
438 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
439 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
440 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
442 tr->transport_stopped_wallclock (*now, xnow, abort);
446 boost::shared_ptr<RouteList> r = routes.reader ();
448 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
449 if (!(*i)->is_hidden()) {
450 (*i)->set_pending_declick (0);
455 commit_reversible_command ();
458 if (_engine.running()) {
459 update_latency_compensation (true, abort);
462 bool const auto_return_enabled =
463 (!config.get_external_sync() && config.get_auto_return());
465 if (auto_return_enabled ||
466 (ptw & PostTransportLocate) ||
467 (_requested_return_frame >= 0) ||
470 if (pending_locate_flush) {
471 flush_all_inserts ();
474 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
475 !(ptw & PostTransportLocate)) {
477 /* no explicit locate queued */
479 bool do_locate = false;
481 if (_requested_return_frame >= 0) {
483 /* explicit return request pre-queued in event list. overrides everything else */
485 cerr << "explicit auto-return to " << _requested_return_frame << endl;
487 _transport_frame = _requested_return_frame;
491 if (config.get_auto_return()) {
495 /* don't try to handle loop play when synced to JACK */
497 if (!synced_to_jack()) {
499 Location *location = _locations.auto_loop_location();
502 _transport_frame = location->start();
504 _transport_frame = _last_roll_location;
509 } else if (_play_range) {
511 /* return to start of range */
513 if (!current_audio_range.empty()) {
514 _transport_frame = current_audio_range.front().start;
520 /* regular auto-return */
522 _transport_frame = _last_roll_location;
528 _requested_return_frame = -1;
531 _engine.transport_locate (_transport_frame);
537 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
540 if (ptw & PostTransportClearSubstate) {
545 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
547 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
548 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
549 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
550 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
551 if (tr && !tr->hidden()) {
552 tr->non_realtime_locate (_transport_frame);
555 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
557 /* we will be back */
564 send_full_time_code (0);
565 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
566 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
568 if ((ptw & PostTransportLocate) && get_record_enabled()) {
569 /* capture start has been changed, so save pending state */
570 save_state ("", true);
574 /* always try to get rid of this */
576 remove_pending_capture_state ();
578 /* save the current state of things if appropriate */
580 if (did_record && !saved) {
581 save_state (_current_snapshot_name);
584 if (ptw & PostTransportStop) {
589 // can't cast away volatile so copy and emit that
590 nframes64_t tframe = _transport_frame;
591 PositionChanged (tframe); /* EMIT SIGNAL */
592 TransportStateChange (); /* EMIT SIGNAL */
594 /* and start it up again if relevant */
596 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
597 request_transport_speed (1.0);
598 pending_locate_roll = false;
603 Session::check_declick_out ()
605 bool locate_required = transport_sub_state & PendingLocate;
607 /* this is called after a process() iteration. if PendingDeclickOut was set,
608 it means that we were waiting to declick the output (which has just been
609 done) before doing something else. this is where we do that "something else".
611 note: called from the audio thread.
614 if (transport_sub_state & PendingDeclickOut) {
616 if (locate_required) {
617 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
618 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
620 stop_transport (pending_abort);
621 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
627 Session::unset_play_loop ()
630 clear_events (SessionEvent::AutoLoop);
632 // set all tracks to NOT use internal looping
633 boost::shared_ptr<RouteList> rl = routes.reader ();
634 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
635 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
636 if (tr && !tr->hidden()) {
643 Session::set_play_loop (bool yn)
645 /* Called from event-handling context */
649 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
650 /* nothing to do, or can't change loop status while recording */
656 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
657 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
658 "Recommend changing the configured options"), PROGRAM_NAME)
671 if (Config->get_seamless_loop()) {
672 // set all tracks to use internal looping
673 boost::shared_ptr<RouteList> rl = routes.reader ();
674 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
675 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
676 if (tr && !tr->hidden()) {
682 // set all tracks to NOT use internal looping
683 boost::shared_ptr<RouteList> rl = routes.reader ();
684 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
685 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
686 if (tr && !tr->hidden()) {
692 /* put the loop event into the event list */
694 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
697 /* locate to start of loop and roll. If doing seamless loop, force a
698 locate+buffer refill even if we are positioned there already.
701 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
709 TransportStateChange ();
712 Session::flush_all_inserts ()
714 boost::shared_ptr<RouteList> r = routes.reader ();
716 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
717 (*i)->flush_processors ();
722 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
724 if (synced_to_jack()) {
729 _slave->speed_and_position (sp, pos);
731 if (target_frame != pos) {
733 /* tell JACK to change transport position, and we will
734 follow along later in ::follow_slave()
737 _engine.transport_locate (target_frame);
739 if (sp != 1.0f && with_roll) {
740 _engine.transport_start ();
746 locate (target_frame, with_roll, with_flush, with_loop, force);
751 Session::micro_locate (nframes_t distance)
753 boost::shared_ptr<RouteList> rl = routes.reader();
754 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
755 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
756 if (tr && !tr->can_internal_playback_seek (distance)) {
761 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
762 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
764 tr->internal_playback_seek (distance);
768 _transport_frame += distance;
772 /** @param with_mmc true to send a MMC locate command when the locate is done */
774 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
776 if (actively_recording() && !with_loop) {
780 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
782 set_transport_speed (1.0, false);
784 loop_changing = false;
788 // Update Timecode time
789 // [DR] FIXME: find out exactly where this should go below
790 _transport_frame = target_frame;
791 timecode_time(_transport_frame, transmitting_timecode_time);
792 outbound_mtc_timecode_frame = _transport_frame;
793 next_quarter_frame_to_send = 0;
795 if (_transport_speed && (!with_loop || loop_changing)) {
796 /* schedule a declick. we'll be called again when its done */
798 if (!(transport_sub_state & PendingDeclickOut)) {
799 transport_sub_state |= (PendingDeclickOut|PendingLocate);
800 pending_locate_frame = target_frame;
801 pending_locate_roll = with_roll;
802 pending_locate_flush = with_flush;
807 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
808 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
811 if (force || !with_loop || loop_changing) {
813 PostTransportWork todo = PostTransportLocate;
816 todo = PostTransportWork (todo | PostTransportRoll);
819 add_post_transport_work (todo);
820 _butler->schedule_transport_work ();
824 /* this is functionally what clear_clicks() does but with a tentative lock */
826 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
828 if (clickm.locked()) {
830 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
839 /* switch from input if we're going to roll */
840 if (Config->get_monitoring_model() == HardwareMonitoring) {
842 boost::shared_ptr<RouteList> rl = routes.reader();
843 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
844 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
845 if (tr && tr->record_enabled ()) {
846 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
847 tr->monitor_input (!config.get_auto_input());
852 /* otherwise we're going to stop, so do the opposite */
853 if (Config->get_monitoring_model() == HardwareMonitoring) {
855 boost::shared_ptr<RouteList> rl = routes.reader();
856 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
857 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
858 if (tr && tr->record_enabled ()) {
859 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
860 tr->monitor_input (true);
866 /* cancel looped playback if transport pos outside of loop range */
868 Location* al = _locations.auto_loop_location();
870 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
871 // cancel looping directly, this is called from event handling context
872 set_play_loop (false);
874 else if (al && _transport_frame == al->start()) {
876 // this is only necessary for seamless looping
878 boost::shared_ptr<RouteList> rl = routes.reader();
879 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
880 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
881 if (tr && tr->record_enabled ()) {
882 // tell it we've looped, so it can deal with the record state
883 tr->transport_looped(_transport_frame);
888 TransportLooped(); // EMIT SIGNAL
892 loop_changing = false;
894 _send_timecode_update = true;
897 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
900 Located (); /* EMIT SIGNAL */
903 /** Set the transport speed.
904 * @param speed New speed
908 Session::set_transport_speed (double speed, bool abort, bool clear_state)
910 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));
912 if (_transport_speed == speed) {
916 _target_transport_speed = fabs(speed);
918 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
919 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
923 speed = min (8.0, speed);
924 } else if (speed < 0) {
925 speed = max (-8.0, speed);
928 if (transport_rolling() && speed == 0.0) {
930 /* we are rolling and we want to stop */
932 if (Config->get_monitoring_model() == HardwareMonitoring)
934 boost::shared_ptr<RouteList> rl = routes.reader();
935 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
936 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
937 if (tr && tr->record_enabled ()) {
938 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
939 tr->monitor_input (true);
944 if (synced_to_jack ()) {
946 /* do this here because our response to the slave won't
952 _engine.transport_stop ();
954 stop_transport (abort);
957 } else if (transport_stopped() && speed == 1.0) {
959 /* we are stopped and we want to start rolling at speed 1 */
961 if (Config->get_monitoring_model() == HardwareMonitoring) {
963 boost::shared_ptr<RouteList> rl = routes.reader();
964 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
965 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
966 if (config.get_auto_input() && tr && tr->record_enabled ()) {
967 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
968 tr->monitor_input (false);
973 if (synced_to_jack()) {
974 _engine.transport_start ();
981 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
982 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
988 if (actively_recording()) {
992 if (speed > 0.0 && _transport_frame == current_end_frame()) {
996 if (speed < 0.0 && _transport_frame == 0) {
1002 /* if we are reversing relative to the current speed, or relative to the speed
1003 before the last stop, then we have to do extra work.
1006 PostTransportWork todo = PostTransportWork (0);
1008 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1009 todo = PostTransportWork (todo | PostTransportReverse);
1010 _last_roll_or_reversal_location = _transport_frame;
1013 _last_transport_speed = _transport_speed;
1014 _transport_speed = speed;
1016 boost::shared_ptr<RouteList> rl = routes.reader();
1017 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1018 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1019 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1020 todo = PostTransportWork (todo | PostTransportSpeed);
1026 add_post_transport_work (todo);
1027 _butler->schedule_transport_work ();
1033 /** Stop the transport. */
1035 Session::stop_transport (bool abort, bool clear_state)
1037 if (_transport_speed == 0.0f) {
1041 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1043 boost::shared_ptr<RouteList> rl = routes.reader();
1044 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1045 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1047 tr->prepare_to_stop (_transport_frame);
1051 /* we need to capture the audio that has still not yet been received by the system
1052 at the time the stop is requested, so we have to roll past that time.
1054 we want to declick before stopping, so schedule the autostop for one
1055 block before the actual end. we'll declick in the subsequent block,
1056 and then we'll really be stopped.
1059 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1060 _transport_frame + _worst_output_latency - current_block_size,
1064 transport_sub_state |= StopPendingCapture;
1065 pending_abort = abort;
1070 if ((transport_sub_state & PendingDeclickOut) == 0) {
1072 if (!(transport_sub_state & StopPendingCapture)) {
1073 boost::shared_ptr<RouteList> rl = routes.reader();
1074 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1075 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1077 tr->prepare_to_stop (_transport_frame);
1082 transport_sub_state |= PendingDeclickOut;
1083 /* we'll be called again after the declick */
1084 pending_abort = abort;
1088 realtime_stop (abort, clear_state);
1089 _butler->schedule_transport_work ();
1093 Session::start_transport ()
1095 _last_roll_location = _transport_frame;
1096 _last_roll_or_reversal_location = _transport_frame;
1098 have_looped = false;
1100 /* if record status is Enabled, move it to Recording. if its
1101 already Recording, move it to Disabled.
1104 switch (record_status()) {
1106 if (!config.get_punch_in()) {
1113 disable_record (false);
1121 transport_sub_state |= PendingDeclickIn;
1123 _transport_speed = 1.0;
1124 _target_transport_speed = 1.0;
1126 boost::shared_ptr<RouteList> rl = routes.reader();
1127 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1128 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1130 tr->realtime_set_speed (tr->speed(), true);
1134 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
1136 TransportStateChange (); /* EMIT SIGNAL */
1139 /** Do any transport work in the audio thread that needs to be done after the
1140 * transport thread is finished. Audio thread, realtime safe.
1143 Session::post_transport ()
1145 PostTransportWork ptw = post_transport_work ();
1147 if (ptw & PostTransportAudition) {
1148 if (auditioner && auditioner->auditioning()) {
1149 process_function = &Session::process_audition;
1151 process_function = &Session::process_with_events;
1155 if (ptw & PostTransportStop) {
1157 transport_sub_state = 0;
1160 if (ptw & PostTransportLocate) {
1162 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1166 transport_sub_state = 0;
1171 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1174 set_post_transport_work (PostTransportWork (0));
1178 Session::reset_rf_scale (nframes_t motion)
1180 cumulative_rf_motion += motion;
1182 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1184 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1186 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1198 Session::use_sync_source (Slave* new_slave)
1200 /* Runs in process() context */
1202 bool non_rt_required = false;
1204 /* XXX this deletion is problematic because we're in RT context */
1209 boost::shared_ptr<RouteList> rl = routes.reader();
1210 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1211 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1212 if (tr && !tr->hidden()) {
1213 if (tr->realtime_set_speed (tr->speed(), true)) {
1214 non_rt_required = true;
1216 tr->set_slaved (_slave != 0);
1220 if (non_rt_required) {
1221 add_post_transport_work (PostTransportSpeed);
1222 _butler->schedule_transport_work ();
1229 Session::drop_sync_source ()
1231 request_sync_source (0);
1235 Session::switch_to_sync_source (SyncSource src)
1239 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1243 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1249 new_slave = new MTC_Slave (*this, *_mtc_port);
1252 catch (failed_constructor& err) {
1257 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1263 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1267 if (_midi_clock_port) {
1269 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1272 catch (failed_constructor& err) {
1277 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1283 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1287 new_slave = new JACK_Slave (_engine.jack());
1295 request_sync_source (new_slave);
1299 Session::reverse_track_buffers ()
1301 add_post_transport_work (PostTransportReverse);
1302 _butler->schedule_transport_work ();
1306 Session::set_track_speed (Track* track, double speed)
1308 if (track->realtime_set_speed (speed, false)) {
1309 add_post_transport_work (PostTransportSpeed);
1310 _butler->schedule_transport_work ();
1316 Session::unset_play_range ()
1318 _play_range = false;
1319 _clear_event_type (SessionEvent::RangeStop);
1320 _clear_event_type (SessionEvent::RangeLocate);
1324 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1328 /* Called from event-processing context */
1330 unset_play_range ();
1332 if (range.empty()) {
1333 /* _play_range set to false in unset_play_range()
1335 if (!leave_rolling) {
1336 /* stop transport */
1337 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1345 /* cancel loop play */
1348 list<AudioRange>::size_type sz = range.size();
1352 list<AudioRange>::iterator i = range.begin();
1353 list<AudioRange>::iterator next;
1355 while (i != range.end()) {
1360 /* locating/stopping is subject to delays for declicking.
1363 nframes_t requested_frame = (*i).end;
1365 if (requested_frame > current_block_size) {
1366 requested_frame -= current_block_size;
1368 requested_frame = 0;
1371 if (next == range.end()) {
1372 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1374 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1382 } else if (sz == 1) {
1384 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1389 /* save range so we can do auto-return etc. */
1391 current_audio_range = range;
1393 /* now start rolling at the right place */
1395 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1398 TransportStateChange ();
1402 Session::request_bounded_roll (nframes_t start, nframes_t end)
1404 AudioRange ar (start, end, 0);
1405 list<AudioRange> lar;
1408 request_play_range (&lar, true);
1411 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1413 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1414 ev->target2_frame = start;
1419 Session::engine_halted ()
1423 /* there will be no more calls to process(), so
1424 we'd better clean up for ourselves, right now.
1426 but first, make sure the butler is out of
1430 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1431 set_post_transport_work (PostTransportWork (0));
1434 realtime_stop (false, true);
1435 non_realtime_stop (false, 0, ignored);
1436 transport_sub_state = 0;
1438 TransportStateChange (); /* EMIT SIGNAL */
1443 Session::xrun_recovery ()
1445 // can't cast away volatile so copy and emit that
1446 nframes64_t tframe = _transport_frame;
1447 Xrun (tframe); //EMIT SIGNAL
1449 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1451 /* it didn't actually halt, but we need
1452 to handle things in the same way.
1460 Session::route_processors_changed (RouteProcessorChange c)
1462 if (c.type == RouteProcessorChange::MeterPointChange) {
1466 update_latency_compensation (false, false);
1471 Session::update_latency_compensation (bool with_stop, bool abort)
1473 bool update_jack = false;
1474 PostTransportWork ptw;
1476 if (_state_of_the_state & Deletion) {
1480 _worst_track_latency = 0;
1481 ptw = post_transport_work();
1483 #undef DEBUG_LATENCY
1484 #ifdef DEBUG_LATENCY
1485 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1488 boost::shared_ptr<RouteList> r = routes.reader ();
1490 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1493 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1496 nframes_t old_latency = (*i)->output()->signal_latency ();
1497 nframes_t track_latency = (*i)->update_total_latency ();
1499 if (old_latency != track_latency) {
1500 (*i)->input()->update_port_total_latencies ();
1501 (*i)->output()->update_port_total_latencies ();
1505 if (!(*i)->is_hidden() && ((*i)->active())) {
1506 _worst_track_latency = max (_worst_track_latency, track_latency);
1511 _engine.update_total_latencies ();
1514 #ifdef DEBUG_LATENCY
1515 cerr << "\tworst was " << _worst_track_latency << endl;
1518 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1519 (*i)->set_latency_delay (_worst_track_latency);
1522 set_worst_io_latencies ();
1524 /* reflect any changes in latencies into capture offsets
1527 boost::shared_ptr<RouteList> rl = routes.reader();
1528 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1529 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1531 tr->set_capture_offset ();
1537 Session::allow_auto_play (bool yn)
1539 auto_play_legal = yn;
1543 Session::reset_jack_connection (jack_client_t* jack)
1547 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1548 js->reset_client (jack);
1553 Session::maybe_stop (nframes_t limit)
1555 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1556 if (synced_to_jack () && config.get_jack_time_master ()) {
1557 _engine.transport_stop ();
1558 } else if (!synced_to_jack ()) {