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"
47 using namespace ARDOUR;
51 Session::add_post_transport_work (PostTransportWork ptw)
53 PostTransportWork oldval;
54 PostTransportWork newval;
58 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
59 newval = PostTransportWork (oldval | ptw);
60 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
66 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
70 Session::request_input_change_handling ()
72 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
73 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
79 Session::request_sync_source (Slave* new_slave)
81 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
84 seamless = Config->get_seamless_loop ();
86 if (dynamic_cast<JACK_Slave*>(new_slave)) {
87 /* JACK cannot support seamless looping at present */
88 Config->set_seamless_loop (false);
90 /* reset to whatever the value was before we last switched slaves */
91 Config->set_seamless_loop (_was_seamless);
94 /* save value of seamless from before the switch */
95 _was_seamless = seamless;
97 ev->slave = new_slave;
102 Session::request_transport_speed (double speed)
104 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
105 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
110 Session::request_track_speed (Track* tr, double speed)
112 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
118 Session::request_stop (bool abort, bool clear_state)
120 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
121 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
126 Session::request_locate (nframes_t target_frame, bool with_roll)
128 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
129 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
134 Session::force_locate (nframes64_t target_frame, bool with_roll)
136 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
137 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
142 Session::request_play_loop (bool yn, bool leave_rolling)
145 Location *location = _locations.auto_loop_location();
147 if (location == 0 && yn) {
148 error << _("Cannot loop - no loop range defined")
153 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
154 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
157 if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
158 // request an immediate locate to refresh the tracks
159 // after disabling looping
160 request_locate (_transport_frame-1, false);
165 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
167 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
169 ev->audio_range = *range;
171 ev->audio_range.clear ();
173 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
178 Session::realtime_stop (bool abort, bool clear_state)
180 DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
181 PostTransportWork todo = PostTransportWork (0);
183 /* assume that when we start, we'll be moving forwards */
185 if (_transport_speed < 0.0f) {
186 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
188 todo = PostTransportWork (todo | PostTransportStop);
191 if (actively_recording()) {
193 /* move the transport position back to where the
194 request for a stop was noticed. we rolled
195 past that point to pick up delayed input (and/or to delick)
198 if (_worst_output_latency > current_block_size) {
199 /* we rolled past the stop point to pick up data that had
200 not yet arrived. move back to where the stop occured.
202 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
204 decrement_transport_position (current_block_size);
207 /* the duration change is not guaranteed to have happened, but is likely */
209 todo = PostTransportWork (todo | PostTransportDuration);
213 todo = PostTransportWork (todo | PostTransportAbort);
217 todo = PostTransportWork (todo | PostTransportClearSubstate);
221 add_post_transport_work (todo);
224 _clear_event_type (SessionEvent::StopOnce);
225 _clear_event_type (SessionEvent::RangeStop);
226 _clear_event_type (SessionEvent::RangeLocate);
228 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
229 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
231 reset_slave_state ();
233 _transport_speed = 0;
234 _target_transport_speed = 0;
236 g_atomic_int_set (&_playback_load, 100);
237 g_atomic_int_set (&_capture_load, 100);
239 if (config.get_use_video_sync()) {
240 waiting_for_sync_offset = true;
243 transport_sub_state = 0;
247 Session::butler_transport_work ()
251 PostTransportWork ptw;
252 boost::shared_ptr<RouteList> r = routes.reader ();
254 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
256 ptw = post_transport_work();
258 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
260 if (ptw & PostTransportAdjustPlaybackBuffering) {
261 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
262 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
264 tr->adjust_playback_buffering ();
265 /* and refill those buffers ... */
266 tr->non_realtime_locate (_transport_frame);
272 if (ptw & PostTransportAdjustCaptureBuffering) {
273 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
274 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
276 tr->adjust_capture_buffering ();
281 if (ptw & PostTransportCurveRealloc) {
282 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
283 (*i)->curve_reallocate();
287 if (ptw & PostTransportInputChange) {
288 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
289 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
291 tr->non_realtime_input_change ();
296 if (ptw & PostTransportSpeed) {
297 non_realtime_set_speed ();
300 if (ptw & PostTransportReverse) {
303 cumulative_rf_motion = 0;
306 /* don't seek if locate will take care of that in non_realtime_stop() */
308 if (!(ptw & PostTransportLocate)) {
310 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
311 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
312 if (tr && !tr->hidden()) {
313 tr->non_realtime_locate (_transport_frame);
315 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
316 /* new request, stop seeking, and start again */
317 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
324 if (ptw & PostTransportLocate) {
325 non_realtime_locate ();
328 if (ptw & PostTransportStop) {
329 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
331 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
336 if (ptw & PostTransportOverWrite) {
337 non_realtime_overwrite (on_entry, finished);
339 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
344 if (ptw & PostTransportAudition) {
345 non_realtime_set_audition ();
348 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
350 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
354 Session::non_realtime_set_speed ()
356 boost::shared_ptr<RouteList> rl = routes.reader();
357 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
358 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
360 tr->non_realtime_set_speed ();
366 Session::non_realtime_overwrite (int on_entry, bool& finished)
368 boost::shared_ptr<RouteList> rl = routes.reader();
369 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
370 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
371 if (tr && tr->pending_overwrite ()) {
372 tr->overwrite_existing_buffers ();
374 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
383 Session::non_realtime_locate ()
385 boost::shared_ptr<RouteList> rl = routes.reader();
386 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
387 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
389 tr->non_realtime_locate (_transport_frame);
396 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
402 PostTransportWork ptw = post_transport_work();
407 boost::shared_ptr<RouteList> rl = routes.reader();
408 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
409 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
410 if (tr && tr->get_captured_frames () != 0) {
416 /* stop and locate are merged here because they share a lot of common stuff */
419 now = localtime (&xnow);
422 auditioner->cancel_audition ();
426 cumulative_rf_motion = 0;
430 begin_reversible_command ("capture");
431 _have_captured = true;
434 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
436 if (abort && did_record) {
437 /* no reason to save the session file when we remove sources
439 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
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 if (abort && did_record) {
450 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
453 boost::shared_ptr<RouteList> r = routes.reader ();
455 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
456 if (!(*i)->is_hidden()) {
457 (*i)->set_pending_declick (0);
462 commit_reversible_command ();
465 if (_engine.running()) {
466 update_latency_compensation (true, abort);
469 bool const auto_return_enabled =
470 (!config.get_external_sync() && config.get_auto_return());
472 if (auto_return_enabled ||
473 (ptw & PostTransportLocate) ||
474 (_requested_return_frame >= 0) ||
477 if (pending_locate_flush) {
478 flush_all_inserts ();
481 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
482 !(ptw & PostTransportLocate)) {
484 /* no explicit locate queued */
486 bool do_locate = false;
488 if (_requested_return_frame >= 0) {
490 /* explicit return request pre-queued in event list. overrides everything else */
492 cerr << "explicit auto-return to " << _requested_return_frame << endl;
494 _transport_frame = _requested_return_frame;
498 if (config.get_auto_return()) {
502 /* don't try to handle loop play when synced to JACK */
504 if (!synced_to_jack()) {
506 Location *location = _locations.auto_loop_location();
509 _transport_frame = location->start();
511 _transport_frame = _last_roll_location;
516 } else if (_play_range) {
518 /* return to start of range */
520 if (!current_audio_range.empty()) {
521 _transport_frame = current_audio_range.front().start;
527 /* regular auto-return */
529 _transport_frame = _last_roll_location;
535 _requested_return_frame = -1;
538 _engine.transport_locate (_transport_frame);
544 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
547 if (ptw & PostTransportClearSubstate) {
552 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
554 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
555 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
556 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
557 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
558 if (tr && !tr->hidden()) {
559 tr->non_realtime_locate (_transport_frame);
562 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
564 /* we will be back */
571 send_full_time_code (_transport_frame);
572 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
573 send_mmc_locate (_transport_frame);
575 if ((ptw & PostTransportLocate) && get_record_enabled()) {
576 /* capture start has been changed, so save pending state */
577 save_state ("", true);
581 /* always try to get rid of this */
583 remove_pending_capture_state ();
585 /* save the current state of things if appropriate */
587 if (did_record && !saved) {
588 save_state (_current_snapshot_name);
591 if (ptw & PostTransportStop) {
596 // can't cast away volatile so copy and emit that
597 nframes64_t tframe = _transport_frame;
598 PositionChanged (tframe); /* EMIT SIGNAL */
599 TransportStateChange (); /* EMIT SIGNAL */
601 /* and start it up again if relevant */
603 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
604 request_transport_speed (1.0);
605 pending_locate_roll = false;
610 Session::check_declick_out ()
612 bool locate_required = transport_sub_state & PendingLocate;
614 /* this is called after a process() iteration. if PendingDeclickOut was set,
615 it means that we were waiting to declick the output (which has just been
616 done) before doing something else. this is where we do that "something else".
618 note: called from the audio thread.
621 if (transport_sub_state & PendingDeclickOut) {
623 if (locate_required) {
624 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
625 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
627 stop_transport (pending_abort);
628 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
634 Session::unset_play_loop ()
637 clear_events (SessionEvent::AutoLoop);
639 // set all tracks to NOT use internal looping
640 boost::shared_ptr<RouteList> rl = routes.reader ();
641 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
642 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
643 if (tr && !tr->hidden()) {
650 Session::set_play_loop (bool yn)
652 /* Called from event-handling context */
656 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
657 /* nothing to do, or can't change loop status while recording */
663 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
664 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
665 "Recommend changing the configured options"), PROGRAM_NAME)
678 if (Config->get_seamless_loop()) {
679 // set all tracks to use internal looping
680 boost::shared_ptr<RouteList> rl = routes.reader ();
681 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
682 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
683 if (tr && !tr->hidden()) {
689 // set all tracks to NOT use internal looping
690 boost::shared_ptr<RouteList> rl = routes.reader ();
691 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
692 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
693 if (tr && !tr->hidden()) {
699 /* put the loop event into the event list */
701 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
704 /* locate to start of loop and roll. If doing seamless loop, force a
705 locate+buffer refill even if we are positioned there already.
708 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
716 TransportStateChange ();
719 Session::flush_all_inserts ()
721 boost::shared_ptr<RouteList> r = routes.reader ();
723 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
724 (*i)->flush_processors ();
729 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
731 if (synced_to_jack()) {
736 _slave->speed_and_position (sp, pos);
738 if (target_frame != pos) {
740 /* tell JACK to change transport position, and we will
741 follow along later in ::follow_slave()
744 _engine.transport_locate (target_frame);
746 if (sp != 1.0f && with_roll) {
747 _engine.transport_start ();
753 locate (target_frame, with_roll, with_flush, with_loop, force);
758 Session::micro_locate (nframes_t distance)
760 boost::shared_ptr<RouteList> rl = routes.reader();
761 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
762 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
763 if (tr && !tr->can_internal_playback_seek (distance)) {
768 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
769 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
771 tr->internal_playback_seek (distance);
775 _transport_frame += distance;
779 /** @param with_mmc true to send a MMC locate command when the locate is done */
781 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
783 if (actively_recording() && !with_loop) {
787 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
789 set_transport_speed (1.0, false);
791 loop_changing = false;
792 Located (); /* EMIT SIGNAL */
796 // Update Timecode time
797 // [DR] FIXME: find out exactly where this should go below
798 _transport_frame = target_frame;
799 timecode_time(_transport_frame, transmitting_timecode_time);
800 outbound_mtc_timecode_frame = _transport_frame;
801 next_quarter_frame_to_send = 0;
803 if (_transport_speed && (!with_loop || loop_changing)) {
804 /* schedule a declick. we'll be called again when its done */
806 if (!(transport_sub_state & PendingDeclickOut)) {
807 transport_sub_state |= (PendingDeclickOut|PendingLocate);
808 pending_locate_frame = target_frame;
809 pending_locate_roll = with_roll;
810 pending_locate_flush = with_flush;
815 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
816 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
819 if (force || !with_loop || loop_changing) {
821 PostTransportWork todo = PostTransportLocate;
824 todo = PostTransportWork (todo | PostTransportRoll);
827 add_post_transport_work (todo);
828 _butler->schedule_transport_work ();
832 /* this is functionally what clear_clicks() does but with a tentative lock */
834 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
836 if (clickm.locked()) {
838 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
847 /* switch from input if we're going to roll */
848 if (Config->get_monitoring_model() == HardwareMonitoring) {
850 boost::shared_ptr<RouteList> rl = routes.reader();
851 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
852 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
853 if (tr && tr->record_enabled ()) {
854 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
855 tr->monitor_input (!config.get_auto_input());
860 /* otherwise we're going to stop, so do the opposite */
861 if (Config->get_monitoring_model() == HardwareMonitoring) {
863 boost::shared_ptr<RouteList> rl = routes.reader();
864 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
865 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
866 if (tr && tr->record_enabled ()) {
867 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
868 tr->monitor_input (true);
874 /* cancel looped playback if transport pos outside of loop range */
876 Location* al = _locations.auto_loop_location();
878 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
879 // cancel looping directly, this is called from event handling context
880 set_play_loop (false);
882 else if (al && _transport_frame == al->start()) {
884 // this is only necessary for seamless looping
886 boost::shared_ptr<RouteList> rl = routes.reader();
887 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
888 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
889 if (tr && tr->record_enabled ()) {
890 // tell it we've looped, so it can deal with the record state
891 tr->transport_looped(_transport_frame);
896 TransportLooped(); // EMIT SIGNAL
900 loop_changing = false;
902 _send_timecode_update = true;
905 send_mmc_locate (_transport_frame);
908 Located (); /* EMIT SIGNAL */
911 /** Set the transport speed.
912 * @param speed New speed
916 Session::set_transport_speed (double speed, bool abort, bool clear_state)
918 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));
920 if (_transport_speed == speed) {
924 _target_transport_speed = fabs(speed);
926 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
927 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
931 speed = min (8.0, speed);
932 } else if (speed < 0) {
933 speed = max (-8.0, speed);
936 if (transport_rolling() && speed == 0.0) {
938 /* we are rolling and we want to stop */
940 if (Config->get_monitoring_model() == HardwareMonitoring)
942 boost::shared_ptr<RouteList> rl = routes.reader();
943 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
944 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
945 if (tr && tr->record_enabled ()) {
946 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
947 tr->monitor_input (true);
952 if (synced_to_jack ()) {
954 /* do this here because our response to the slave won't
960 _engine.transport_stop ();
962 stop_transport (abort);
965 } else if (transport_stopped() && speed == 1.0) {
967 /* we are stopped and we want to start rolling at speed 1 */
969 if (Config->get_monitoring_model() == HardwareMonitoring) {
971 boost::shared_ptr<RouteList> rl = routes.reader();
972 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
973 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
974 if (config.get_auto_input() && tr && tr->record_enabled ()) {
975 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
976 tr->monitor_input (false);
981 if (synced_to_jack()) {
982 _engine.transport_start ();
989 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
990 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
996 if (actively_recording()) {
1000 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1004 if (speed < 0.0 && _transport_frame == 0) {
1010 /* if we are reversing relative to the current speed, or relative to the speed
1011 before the last stop, then we have to do extra work.
1014 PostTransportWork todo = PostTransportWork (0);
1016 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1017 todo = PostTransportWork (todo | PostTransportReverse);
1018 _last_roll_or_reversal_location = _transport_frame;
1021 _last_transport_speed = _transport_speed;
1022 _transport_speed = speed;
1024 boost::shared_ptr<RouteList> rl = routes.reader();
1025 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1026 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1027 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1028 todo = PostTransportWork (todo | PostTransportSpeed);
1034 add_post_transport_work (todo);
1035 _butler->schedule_transport_work ();
1041 /** Stop the transport. */
1043 Session::stop_transport (bool abort, bool clear_state)
1045 if (_transport_speed == 0.0f) {
1049 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1051 boost::shared_ptr<RouteList> rl = routes.reader();
1052 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1053 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1055 tr->prepare_to_stop (_transport_frame);
1059 /* we need to capture the audio that has still not yet been received by the system
1060 at the time the stop is requested, so we have to roll past that time.
1062 we want to declick before stopping, so schedule the autostop for one
1063 block before the actual end. we'll declick in the subsequent block,
1064 and then we'll really be stopped.
1067 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1068 _transport_frame + _worst_output_latency - current_block_size,
1072 transport_sub_state |= StopPendingCapture;
1073 pending_abort = abort;
1078 if ((transport_sub_state & PendingDeclickOut) == 0) {
1080 if (!(transport_sub_state & StopPendingCapture)) {
1081 boost::shared_ptr<RouteList> rl = routes.reader();
1082 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1083 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1085 tr->prepare_to_stop (_transport_frame);
1090 transport_sub_state |= PendingDeclickOut;
1091 /* we'll be called again after the declick */
1092 pending_abort = abort;
1096 realtime_stop (abort, clear_state);
1097 _butler->schedule_transport_work ();
1101 Session::start_transport ()
1103 _last_roll_location = _transport_frame;
1104 _last_roll_or_reversal_location = _transport_frame;
1106 have_looped = false;
1108 /* if record status is Enabled, move it to Recording. if its
1109 already Recording, move it to Disabled.
1112 switch (record_status()) {
1114 if (!config.get_punch_in()) {
1121 disable_record (false);
1129 transport_sub_state |= PendingDeclickIn;
1131 _transport_speed = 1.0;
1132 _target_transport_speed = 1.0;
1134 boost::shared_ptr<RouteList> rl = routes.reader();
1135 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1136 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1138 tr->realtime_set_speed (tr->speed(), true);
1142 Timecode::Time time;
1143 timecode_time_subframes (_transport_frame, time);
1144 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1146 TransportStateChange (); /* EMIT SIGNAL */
1149 /** Do any transport work in the audio thread that needs to be done after the
1150 * transport thread is finished. Audio thread, realtime safe.
1153 Session::post_transport ()
1155 PostTransportWork ptw = post_transport_work ();
1157 if (ptw & PostTransportAudition) {
1158 if (auditioner && auditioner->auditioning()) {
1159 process_function = &Session::process_audition;
1161 process_function = &Session::process_with_events;
1165 if (ptw & PostTransportStop) {
1167 transport_sub_state = 0;
1170 if (ptw & PostTransportLocate) {
1172 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1176 transport_sub_state = 0;
1181 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1184 set_post_transport_work (PostTransportWork (0));
1188 Session::reset_rf_scale (nframes_t motion)
1190 cumulative_rf_motion += motion;
1192 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1194 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1196 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1208 Session::use_sync_source (Slave* new_slave)
1210 /* Runs in process() context */
1212 bool non_rt_required = false;
1214 /* XXX this deletion is problematic because we're in RT context */
1219 boost::shared_ptr<RouteList> rl = routes.reader();
1220 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1221 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1222 if (tr && !tr->hidden()) {
1223 if (tr->realtime_set_speed (tr->speed(), true)) {
1224 non_rt_required = true;
1226 tr->set_slaved (_slave != 0);
1230 if (non_rt_required) {
1231 add_post_transport_work (PostTransportSpeed);
1232 _butler->schedule_transport_work ();
1239 Session::drop_sync_source ()
1241 request_sync_source (0);
1245 Session::switch_to_sync_source (SyncSource src)
1249 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1253 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1258 new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
1261 catch (failed_constructor& err) {
1267 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1272 new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
1275 catch (failed_constructor& err) {
1281 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1285 new_slave = new JACK_Slave (_engine.jack());
1293 request_sync_source (new_slave);
1297 Session::reverse_track_buffers ()
1299 add_post_transport_work (PostTransportReverse);
1300 _butler->schedule_transport_work ();
1304 Session::set_track_speed (Track* track, double speed)
1306 if (track->realtime_set_speed (speed, false)) {
1307 add_post_transport_work (PostTransportSpeed);
1308 _butler->schedule_transport_work ();
1314 Session::unset_play_range ()
1316 _play_range = false;
1317 _clear_event_type (SessionEvent::RangeStop);
1318 _clear_event_type (SessionEvent::RangeLocate);
1322 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1326 /* Called from event-processing context */
1328 unset_play_range ();
1330 if (range.empty()) {
1331 /* _play_range set to false in unset_play_range()
1333 if (!leave_rolling) {
1334 /* stop transport */
1335 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1343 /* cancel loop play */
1346 list<AudioRange>::size_type sz = range.size();
1350 list<AudioRange>::iterator i = range.begin();
1351 list<AudioRange>::iterator next;
1353 while (i != range.end()) {
1358 /* locating/stopping is subject to delays for declicking.
1361 nframes_t requested_frame = (*i).end;
1363 if (requested_frame > current_block_size) {
1364 requested_frame -= current_block_size;
1366 requested_frame = 0;
1369 if (next == range.end()) {
1370 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1372 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1380 } else if (sz == 1) {
1382 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1387 /* save range so we can do auto-return etc. */
1389 current_audio_range = range;
1391 /* now start rolling at the right place */
1393 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1396 TransportStateChange ();
1400 Session::request_bounded_roll (nframes_t start, nframes_t end)
1402 AudioRange ar (start, end, 0);
1403 list<AudioRange> lar;
1406 request_play_range (&lar, true);
1409 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1411 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1412 ev->target2_frame = start;
1417 Session::engine_halted ()
1421 /* there will be no more calls to process(), so
1422 we'd better clean up for ourselves, right now.
1424 but first, make sure the butler is out of
1428 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1429 set_post_transport_work (PostTransportWork (0));
1432 realtime_stop (false, true);
1433 non_realtime_stop (false, 0, ignored);
1434 transport_sub_state = 0;
1436 TransportStateChange (); /* EMIT SIGNAL */
1441 Session::xrun_recovery ()
1443 // can't cast away volatile so copy and emit that
1444 nframes64_t tframe = _transport_frame;
1445 Xrun (tframe); //EMIT SIGNAL
1447 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1449 /* it didn't actually halt, but we need
1450 to handle things in the same way.
1458 Session::route_processors_changed (RouteProcessorChange c)
1460 if (c.type == RouteProcessorChange::MeterPointChange) {
1464 update_latency_compensation (false, false);
1469 Session::update_latency_compensation (bool with_stop, bool abort)
1471 bool update_jack = false;
1472 PostTransportWork ptw;
1474 if (_state_of_the_state & Deletion) {
1478 _worst_track_latency = 0;
1479 ptw = post_transport_work();
1481 #undef DEBUG_LATENCY
1482 #ifdef DEBUG_LATENCY
1483 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1486 boost::shared_ptr<RouteList> r = routes.reader ();
1488 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1491 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1494 nframes_t old_latency = (*i)->output()->signal_latency ();
1495 nframes_t track_latency = (*i)->update_total_latency ();
1497 if (old_latency != track_latency) {
1498 (*i)->input()->update_port_total_latencies ();
1499 (*i)->output()->update_port_total_latencies ();
1503 if (!(*i)->is_hidden() && ((*i)->active())) {
1504 _worst_track_latency = max (_worst_track_latency, track_latency);
1509 _engine.update_total_latencies ();
1512 #ifdef DEBUG_LATENCY
1513 cerr << "\tworst was " << _worst_track_latency << endl;
1516 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1517 (*i)->set_latency_delay (_worst_track_latency);
1520 set_worst_io_latencies ();
1522 /* reflect any changes in latencies into capture offsets
1525 boost::shared_ptr<RouteList> rl = routes.reader();
1526 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1527 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1529 tr->set_capture_offset ();
1535 Session::allow_auto_play (bool yn)
1537 auto_play_legal = yn;
1541 Session::reset_jack_connection (jack_client_t* jack)
1545 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1546 js->reset_client (jack);
1551 Session::maybe_stop (nframes_t limit)
1553 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1554 if (synced_to_jack () && config.get_jack_time_master ()) {
1555 _engine.transport_stop ();
1556 } else if (!synced_to_jack ()) {
1565 Session::send_mmc_locate (nframes64_t t)
1567 Timecode::Time time;
1568 timecode_time_subframes (t, time);
1569 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));