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();
187 timecode_time_subframes (_transport_frame, time);
189 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
190 _mmc->send (MIDI::MachineControlCommand (time));
192 if (_transport_speed < 0.0f) {
193 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
195 todo = PostTransportWork (todo | PostTransportStop);
198 if (actively_recording()) {
200 /* move the transport position back to where the
201 request for a stop was noticed. we rolled
202 past that point to pick up delayed input (and/or to delick)
205 if (_worst_output_latency > current_block_size) {
206 /* we rolled past the stop point to pick up data that had
207 not yet arrived. move back to where the stop occured.
209 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
211 decrement_transport_position (current_block_size);
214 /* the duration change is not guaranteed to have happened, but is likely */
216 todo = PostTransportWork (todo | PostTransportDuration);
220 todo = PostTransportWork (todo | PostTransportAbort);
224 todo = PostTransportWork (todo | PostTransportClearSubstate);
228 add_post_transport_work (todo);
231 _clear_event_type (SessionEvent::StopOnce);
232 _clear_event_type (SessionEvent::RangeStop);
233 _clear_event_type (SessionEvent::RangeLocate);
235 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
236 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
238 reset_slave_state ();
240 _transport_speed = 0;
241 _target_transport_speed = 0;
243 g_atomic_int_set (&_playback_load, 100);
244 g_atomic_int_set (&_capture_load, 100);
246 if (config.get_use_video_sync()) {
247 waiting_for_sync_offset = true;
250 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
254 Session::butler_transport_work ()
258 PostTransportWork ptw;
259 boost::shared_ptr<RouteList> r = routes.reader ();
261 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
263 ptw = post_transport_work();
265 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
267 if (ptw & PostTransportAdjustPlaybackBuffering) {
268 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
269 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
271 tr->adjust_playback_buffering ();
272 /* and refill those buffers ... */
273 tr->non_realtime_locate (_transport_frame);
279 if (ptw & PostTransportAdjustCaptureBuffering) {
280 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
281 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
283 tr->adjust_capture_buffering ();
288 if (ptw & PostTransportCurveRealloc) {
289 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
290 (*i)->curve_reallocate();
294 if (ptw & PostTransportInputChange) {
295 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
296 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
298 tr->non_realtime_input_change ();
303 if (ptw & PostTransportSpeed) {
304 non_realtime_set_speed ();
307 if (ptw & PostTransportReverse) {
310 cumulative_rf_motion = 0;
313 /* don't seek if locate will take care of that in non_realtime_stop() */
315 if (!(ptw & PostTransportLocate)) {
317 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
318 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
319 if (tr && !tr->hidden()) {
320 tr->non_realtime_locate (_transport_frame);
322 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
323 /* new request, stop seeking, and start again */
324 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
331 if (ptw & PostTransportLocate) {
332 non_realtime_locate ();
335 if (ptw & PostTransportStop) {
336 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
338 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
343 if (ptw & PostTransportOverWrite) {
344 non_realtime_overwrite (on_entry, finished);
346 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
351 if (ptw & PostTransportAudition) {
352 non_realtime_set_audition ();
355 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
357 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
361 Session::non_realtime_set_speed ()
363 boost::shared_ptr<RouteList> rl = routes.reader();
364 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
365 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
367 tr->non_realtime_set_speed ();
373 Session::non_realtime_overwrite (int on_entry, bool& finished)
375 boost::shared_ptr<RouteList> rl = routes.reader();
376 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
377 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
378 if (tr && tr->pending_overwrite ()) {
379 tr->overwrite_existing_buffers ();
381 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
390 Session::non_realtime_locate ()
392 boost::shared_ptr<RouteList> rl = routes.reader();
393 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
394 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
396 tr->non_realtime_locate (_transport_frame);
403 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
409 PostTransportWork ptw = post_transport_work();
414 boost::shared_ptr<RouteList> rl = routes.reader();
415 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
416 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
417 if (tr && tr->get_captured_frames () != 0) {
423 /* stop and locate are merged here because they share a lot of common stuff */
426 now = localtime (&xnow);
429 auditioner->cancel_audition ();
433 cumulative_rf_motion = 0;
437 begin_reversible_command ("capture");
438 _have_captured = true;
441 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
442 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
443 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
445 tr->transport_stopped_wallclock (*now, xnow, abort);
449 boost::shared_ptr<RouteList> r = routes.reader ();
451 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
452 if (!(*i)->is_hidden()) {
453 (*i)->set_pending_declick (0);
458 commit_reversible_command ();
461 if (_engine.running()) {
462 update_latency_compensation (true, abort);
465 bool const auto_return_enabled =
466 (!config.get_external_sync() && config.get_auto_return());
468 if (auto_return_enabled ||
469 (ptw & PostTransportLocate) ||
470 (_requested_return_frame >= 0) ||
473 if (pending_locate_flush) {
474 flush_all_inserts ();
477 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
478 !(ptw & PostTransportLocate)) {
480 /* no explicit locate queued */
482 bool do_locate = false;
484 if (_requested_return_frame >= 0) {
486 /* explicit return request pre-queued in event list. overrides everything else */
488 cerr << "explicit auto-return to " << _requested_return_frame << endl;
490 _transport_frame = _requested_return_frame;
494 if (config.get_auto_return()) {
498 /* don't try to handle loop play when synced to JACK */
500 if (!synced_to_jack()) {
502 Location *location = _locations.auto_loop_location();
505 _transport_frame = location->start();
507 _transport_frame = _last_roll_location;
512 } else if (_play_range) {
514 /* return to start of range */
516 if (!current_audio_range.empty()) {
517 _transport_frame = current_audio_range.front().start;
523 /* regular auto-return */
525 _transport_frame = _last_roll_location;
531 _requested_return_frame = -1;
534 _engine.transport_locate (_transport_frame);
540 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
543 if (ptw & PostTransportClearSubstate) {
548 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
550 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
551 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
552 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
553 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
554 if (tr && !tr->hidden()) {
555 tr->non_realtime_locate (_transport_frame);
558 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
560 /* we will be back */
567 send_full_time_code (0);
569 if ((ptw & PostTransportLocate) && get_record_enabled()) {
570 /* capture start has been changed, so save pending state */
571 save_state ("", true);
575 /* always try to get rid of this */
577 remove_pending_capture_state ();
579 /* save the current state of things if appropriate */
581 if (did_record && !saved) {
582 save_state (_current_snapshot_name);
585 if (ptw & PostTransportStop) {
590 // can't cast away volatile so copy and emit that
591 nframes64_t tframe = _transport_frame;
592 PositionChanged (tframe); /* EMIT SIGNAL */
593 TransportStateChange (); /* EMIT SIGNAL */
595 /* and start it up again if relevant */
597 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
598 request_transport_speed (1.0);
599 pending_locate_roll = false;
604 Session::check_declick_out ()
606 bool locate_required = transport_sub_state & PendingLocate;
608 /* this is called after a process() iteration. if PendingDeclickOut was set,
609 it means that we were waiting to declick the output (which has just been
610 done) before doing something else. this is where we do that "something else".
612 note: called from the audio thread.
615 if (transport_sub_state & PendingDeclickOut) {
617 if (locate_required) {
618 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
619 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
621 stop_transport (pending_abort);
622 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
628 Session::unset_play_loop ()
631 clear_events (SessionEvent::AutoLoop);
633 // set all tracks to NOT use internal looping
634 boost::shared_ptr<RouteList> rl = routes.reader ();
635 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
636 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
637 if (tr && !tr->hidden()) {
644 Session::set_play_loop (bool yn)
646 /* Called from event-handling context */
650 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
651 /* nothing to do, or can't change loop status while recording */
657 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
658 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
659 "Recommend changing the configured options"), PROGRAM_NAME)
672 if (Config->get_seamless_loop()) {
673 // set all tracks to use internal looping
674 boost::shared_ptr<RouteList> rl = routes.reader ();
675 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
676 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
677 if (tr && !tr->hidden()) {
683 // set all tracks to NOT use internal looping
684 boost::shared_ptr<RouteList> rl = routes.reader ();
685 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
686 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
687 if (tr && !tr->hidden()) {
693 /* put the loop event into the event list */
695 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
698 /* locate to start of loop and roll. If doing seamless loop, force a
699 locate+buffer refill even if we are positioned there already.
702 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
710 TransportStateChange ();
713 Session::flush_all_inserts ()
715 boost::shared_ptr<RouteList> r = routes.reader ();
717 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
718 (*i)->flush_processors ();
723 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
725 if (synced_to_jack()) {
730 _slave->speed_and_position (sp, pos);
732 if (target_frame != pos) {
734 /* tell JACK to change transport position, and we will
735 follow along later in ::follow_slave()
738 _engine.transport_locate (target_frame);
740 if (sp != 1.0f && with_roll) {
741 _engine.transport_start ();
747 locate (target_frame, with_roll, with_flush, with_loop, force);
752 Session::micro_locate (nframes_t distance)
754 boost::shared_ptr<RouteList> rl = routes.reader();
755 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
756 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
757 if (tr && !tr->can_internal_playback_seek (distance)) {
762 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
763 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
765 tr->internal_playback_seek (distance);
769 _transport_frame += distance;
773 /** @param with_mmc true to send a MMC locate command when the locate is done */
775 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
777 if (actively_recording() && !with_loop) {
781 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
783 set_transport_speed (1.0, false);
785 loop_changing = false;
786 Located (); /* EMIT SIGNAL */
790 // Update Timecode time
791 // [DR] FIXME: find out exactly where this should go below
792 _transport_frame = target_frame;
793 timecode_time(_transport_frame, transmitting_timecode_time);
794 outbound_mtc_timecode_frame = _transport_frame;
795 next_quarter_frame_to_send = 0;
797 if (_transport_speed && (!with_loop || loop_changing)) {
798 /* schedule a declick. we'll be called again when its done */
800 if (!(transport_sub_state & PendingDeclickOut)) {
801 transport_sub_state |= (PendingDeclickOut|PendingLocate);
802 pending_locate_frame = target_frame;
803 pending_locate_roll = with_roll;
804 pending_locate_flush = with_flush;
809 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
810 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
813 if (force || !with_loop || loop_changing) {
815 PostTransportWork todo = PostTransportLocate;
818 todo = PostTransportWork (todo | PostTransportRoll);
821 add_post_transport_work (todo);
822 _butler->schedule_transport_work ();
826 /* this is functionally what clear_clicks() does but with a tentative lock */
828 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
830 if (clickm.locked()) {
832 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
841 /* switch from input if we're going to roll */
842 if (Config->get_monitoring_model() == HardwareMonitoring) {
844 boost::shared_ptr<RouteList> rl = routes.reader();
845 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
846 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
847 if (tr && tr->record_enabled ()) {
848 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
849 tr->monitor_input (!config.get_auto_input());
854 /* otherwise we're going to stop, so do the opposite */
855 if (Config->get_monitoring_model() == HardwareMonitoring) {
857 boost::shared_ptr<RouteList> rl = routes.reader();
858 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
859 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
860 if (tr && tr->record_enabled ()) {
861 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
862 tr->monitor_input (true);
868 /* cancel looped playback if transport pos outside of loop range */
870 Location* al = _locations.auto_loop_location();
872 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
873 // cancel looping directly, this is called from event handling context
874 set_play_loop (false);
876 else if (al && _transport_frame == al->start()) {
878 // this is only necessary for seamless looping
880 boost::shared_ptr<RouteList> rl = routes.reader();
881 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
882 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
883 if (tr && tr->record_enabled ()) {
884 // tell it we've looped, so it can deal with the record state
885 tr->transport_looped(_transport_frame);
890 TransportLooped(); // EMIT SIGNAL
894 loop_changing = false;
896 _send_timecode_update = true;
900 timecode_time_subframes (_transport_frame, time);
901 _mmc->send (MIDI::MachineControlCommand (time));
904 Located (); /* EMIT SIGNAL */
907 /** Set the transport speed.
908 * @param speed New speed
912 Session::set_transport_speed (double speed, bool abort, bool clear_state)
914 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));
916 if (_transport_speed == speed) {
920 _target_transport_speed = fabs(speed);
922 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
923 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
927 speed = min (8.0, speed);
928 } else if (speed < 0) {
929 speed = max (-8.0, speed);
932 if (transport_rolling() && speed == 0.0) {
934 /* we are rolling and we want to stop */
936 if (Config->get_monitoring_model() == HardwareMonitoring)
938 boost::shared_ptr<RouteList> rl = routes.reader();
939 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
940 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
941 if (tr && tr->record_enabled ()) {
942 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
943 tr->monitor_input (true);
948 if (synced_to_jack ()) {
950 /* do this here because our response to the slave won't
956 _engine.transport_stop ();
958 stop_transport (abort);
961 } else if (transport_stopped() && speed == 1.0) {
963 /* we are stopped and we want to start rolling at speed 1 */
965 if (Config->get_monitoring_model() == HardwareMonitoring) {
967 boost::shared_ptr<RouteList> rl = routes.reader();
968 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
969 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
970 if (config.get_auto_input() && tr && tr->record_enabled ()) {
971 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
972 tr->monitor_input (false);
977 if (synced_to_jack()) {
978 _engine.transport_start ();
985 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
986 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
992 if (actively_recording()) {
996 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1000 if (speed < 0.0 && _transport_frame == 0) {
1006 /* if we are reversing relative to the current speed, or relative to the speed
1007 before the last stop, then we have to do extra work.
1010 PostTransportWork todo = PostTransportWork (0);
1012 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1013 todo = PostTransportWork (todo | PostTransportReverse);
1014 _last_roll_or_reversal_location = _transport_frame;
1017 _last_transport_speed = _transport_speed;
1018 _transport_speed = speed;
1020 boost::shared_ptr<RouteList> rl = routes.reader();
1021 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1022 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1023 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1024 todo = PostTransportWork (todo | PostTransportSpeed);
1030 add_post_transport_work (todo);
1031 _butler->schedule_transport_work ();
1037 /** Stop the transport. */
1039 Session::stop_transport (bool abort, bool clear_state)
1041 if (_transport_speed == 0.0f) {
1045 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1047 boost::shared_ptr<RouteList> rl = routes.reader();
1048 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1049 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1051 tr->prepare_to_stop (_transport_frame);
1055 /* we need to capture the audio that has still not yet been received by the system
1056 at the time the stop is requested, so we have to roll past that time.
1058 we want to declick before stopping, so schedule the autostop for one
1059 block before the actual end. we'll declick in the subsequent block,
1060 and then we'll really be stopped.
1063 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1064 _transport_frame + _worst_output_latency - current_block_size,
1068 transport_sub_state |= StopPendingCapture;
1069 pending_abort = abort;
1074 if ((transport_sub_state & PendingDeclickOut) == 0) {
1076 if (!(transport_sub_state & StopPendingCapture)) {
1077 boost::shared_ptr<RouteList> rl = routes.reader();
1078 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1079 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1081 tr->prepare_to_stop (_transport_frame);
1086 transport_sub_state |= PendingDeclickOut;
1087 /* we'll be called again after the declick */
1088 pending_abort = abort;
1092 realtime_stop (abort, clear_state);
1093 _butler->schedule_transport_work ();
1097 Session::start_transport ()
1099 _last_roll_location = _transport_frame;
1100 _last_roll_or_reversal_location = _transport_frame;
1102 have_looped = false;
1104 /* if record status is Enabled, move it to Recording. if its
1105 already Recording, move it to Disabled.
1108 switch (record_status()) {
1110 if (!config.get_punch_in()) {
1117 disable_record (false);
1125 transport_sub_state |= PendingDeclickIn;
1127 _transport_speed = 1.0;
1128 _target_transport_speed = 1.0;
1130 boost::shared_ptr<RouteList> rl = routes.reader();
1131 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1132 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1134 tr->realtime_set_speed (tr->speed(), true);
1138 Timecode::Time time;
1139 timecode_time_subframes (_transport_frame, time);
1140 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1142 TransportStateChange (); /* EMIT SIGNAL */
1145 /** Do any transport work in the audio thread that needs to be done after the
1146 * transport thread is finished. Audio thread, realtime safe.
1149 Session::post_transport ()
1151 PostTransportWork ptw = post_transport_work ();
1153 if (ptw & PostTransportAudition) {
1154 if (auditioner && auditioner->auditioning()) {
1155 process_function = &Session::process_audition;
1157 process_function = &Session::process_with_events;
1161 if (ptw & PostTransportStop) {
1163 transport_sub_state = 0;
1166 if (ptw & PostTransportLocate) {
1168 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1172 transport_sub_state = 0;
1177 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1180 set_post_transport_work (PostTransportWork (0));
1184 Session::reset_rf_scale (nframes_t motion)
1186 cumulative_rf_motion += motion;
1188 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1190 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1192 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1204 Session::use_sync_source (Slave* new_slave)
1206 /* Runs in process() context */
1208 bool non_rt_required = false;
1210 /* XXX this deletion is problematic because we're in RT context */
1215 boost::shared_ptr<RouteList> rl = routes.reader();
1216 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1217 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1218 if (tr && !tr->hidden()) {
1219 if (tr->realtime_set_speed (tr->speed(), true)) {
1220 non_rt_required = true;
1222 tr->set_slaved (_slave != 0);
1226 if (non_rt_required) {
1227 add_post_transport_work (PostTransportSpeed);
1228 _butler->schedule_transport_work ();
1235 Session::drop_sync_source ()
1237 request_sync_source (0);
1241 Session::switch_to_sync_source (SyncSource src)
1245 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1249 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1255 new_slave = new MTC_Slave (*this, *_mtc_port);
1258 catch (failed_constructor& err) {
1263 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1269 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1273 if (_midi_clock_port) {
1275 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1278 catch (failed_constructor& err) {
1283 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1289 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1293 new_slave = new JACK_Slave (_engine.jack());
1301 request_sync_source (new_slave);
1305 Session::reverse_track_buffers ()
1307 add_post_transport_work (PostTransportReverse);
1308 _butler->schedule_transport_work ();
1312 Session::set_track_speed (Track* track, double speed)
1314 if (track->realtime_set_speed (speed, false)) {
1315 add_post_transport_work (PostTransportSpeed);
1316 _butler->schedule_transport_work ();
1322 Session::unset_play_range ()
1324 _play_range = false;
1325 _clear_event_type (SessionEvent::RangeStop);
1326 _clear_event_type (SessionEvent::RangeLocate);
1330 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1334 /* Called from event-processing context */
1336 unset_play_range ();
1338 if (range.empty()) {
1339 /* _play_range set to false in unset_play_range()
1341 if (!leave_rolling) {
1342 /* stop transport */
1343 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1351 /* cancel loop play */
1354 list<AudioRange>::size_type sz = range.size();
1358 list<AudioRange>::iterator i = range.begin();
1359 list<AudioRange>::iterator next;
1361 while (i != range.end()) {
1366 /* locating/stopping is subject to delays for declicking.
1369 nframes_t requested_frame = (*i).end;
1371 if (requested_frame > current_block_size) {
1372 requested_frame -= current_block_size;
1374 requested_frame = 0;
1377 if (next == range.end()) {
1378 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1380 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1388 } else if (sz == 1) {
1390 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1395 /* save range so we can do auto-return etc. */
1397 current_audio_range = range;
1399 /* now start rolling at the right place */
1401 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1404 TransportStateChange ();
1408 Session::request_bounded_roll (nframes_t start, nframes_t end)
1410 AudioRange ar (start, end, 0);
1411 list<AudioRange> lar;
1414 request_play_range (&lar, true);
1417 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1419 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1420 ev->target2_frame = start;
1425 Session::engine_halted ()
1429 /* there will be no more calls to process(), so
1430 we'd better clean up for ourselves, right now.
1432 but first, make sure the butler is out of
1436 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1437 set_post_transport_work (PostTransportWork (0));
1440 realtime_stop (false, true);
1441 non_realtime_stop (false, 0, ignored);
1442 transport_sub_state = 0;
1444 TransportStateChange (); /* EMIT SIGNAL */
1449 Session::xrun_recovery ()
1451 // can't cast away volatile so copy and emit that
1452 nframes64_t tframe = _transport_frame;
1453 Xrun (tframe); //EMIT SIGNAL
1455 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1457 /* it didn't actually halt, but we need
1458 to handle things in the same way.
1466 Session::route_processors_changed (RouteProcessorChange c)
1468 if (c.type == RouteProcessorChange::MeterPointChange) {
1472 update_latency_compensation (false, false);
1477 Session::update_latency_compensation (bool with_stop, bool abort)
1479 bool update_jack = false;
1480 PostTransportWork ptw;
1482 if (_state_of_the_state & Deletion) {
1486 _worst_track_latency = 0;
1487 ptw = post_transport_work();
1489 #undef DEBUG_LATENCY
1490 #ifdef DEBUG_LATENCY
1491 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1494 boost::shared_ptr<RouteList> r = routes.reader ();
1496 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1499 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1502 nframes_t old_latency = (*i)->output()->signal_latency ();
1503 nframes_t track_latency = (*i)->update_total_latency ();
1505 if (old_latency != track_latency) {
1506 (*i)->input()->update_port_total_latencies ();
1507 (*i)->output()->update_port_total_latencies ();
1511 if (!(*i)->is_hidden() && ((*i)->active())) {
1512 _worst_track_latency = max (_worst_track_latency, track_latency);
1517 _engine.update_total_latencies ();
1520 #ifdef DEBUG_LATENCY
1521 cerr << "\tworst was " << _worst_track_latency << endl;
1524 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1525 (*i)->set_latency_delay (_worst_track_latency);
1528 set_worst_io_latencies ();
1530 /* reflect any changes in latencies into capture offsets
1533 boost::shared_ptr<RouteList> rl = routes.reader();
1534 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1535 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1537 tr->set_capture_offset ();
1543 Session::allow_auto_play (bool yn)
1545 auto_play_legal = yn;
1549 Session::reset_jack_connection (jack_client_t* jack)
1553 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1554 js->reset_client (jack);
1559 Session::maybe_stop (nframes_t limit)
1561 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1562 if (synced_to_jack () && config.get_jack_time_master ()) {
1563 _engine.transport_stop ();
1564 } else if (!synced_to_jack ()) {