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 if (config.get_use_video_sync()) {
241 waiting_for_sync_offset = true;
244 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
248 Session::butler_transport_work ()
252 PostTransportWork ptw;
253 boost::shared_ptr<RouteList> r = routes.reader ();
255 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
257 ptw = post_transport_work();
259 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
261 if (ptw & PostTransportCurveRealloc) {
262 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
263 (*i)->curve_reallocate();
267 if (ptw & PostTransportInputChange) {
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->non_realtime_input_change ();
276 if (ptw & PostTransportSpeed) {
277 non_realtime_set_speed ();
280 if (ptw & PostTransportReverse) {
283 cumulative_rf_motion = 0;
286 /* don't seek if locate will take care of that in non_realtime_stop() */
288 if (!(ptw & PostTransportLocate)) {
290 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
291 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
292 if (tr && !tr->hidden()) {
293 tr->non_realtime_locate (_transport_frame);
295 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
296 /* new request, stop seeking, and start again */
297 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
304 if (ptw & PostTransportLocate) {
305 non_realtime_locate ();
308 if (ptw & PostTransportStop) {
309 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
311 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
316 if (ptw & PostTransportOverWrite) {
317 non_realtime_overwrite (on_entry, finished);
319 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
324 if (ptw & PostTransportAudition) {
325 non_realtime_set_audition ();
328 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
330 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
334 Session::non_realtime_set_speed ()
336 boost::shared_ptr<RouteList> rl = routes.reader();
337 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
338 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
340 tr->non_realtime_set_speed ();
346 Session::non_realtime_overwrite (int on_entry, bool& finished)
348 boost::shared_ptr<RouteList> rl = routes.reader();
349 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
350 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
351 if (tr && tr->pending_overwrite ()) {
352 tr->overwrite_existing_buffers ();
354 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
363 Session::non_realtime_locate ()
365 boost::shared_ptr<RouteList> rl = routes.reader();
366 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
367 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
369 tr->non_realtime_locate (_transport_frame);
376 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
382 PostTransportWork ptw = post_transport_work();
387 boost::shared_ptr<RouteList> rl = routes.reader();
388 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
389 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
390 if (tr && tr->get_captured_frames () != 0) {
396 /* stop and locate are merged here because they share a lot of common stuff */
399 now = localtime (&xnow);
402 auditioner->cancel_audition ();
406 cumulative_rf_motion = 0;
410 begin_reversible_command ("capture");
412 Location* loc = _locations.session_range_location();
413 bool change_end = false;
415 if (_transport_frame < loc->end()) {
417 /* stopped recording before current end */
419 if (config.get_end_marker_is_free()) {
421 /* first capture for this session, move end back to where we are */
426 } else if (_transport_frame > loc->end()) {
428 /* stopped recording after the current end, extend it */
434 XMLNode &before = loc->get_state();
435 loc->set_end(_transport_frame);
436 XMLNode &after = loc->get_state();
437 add_command (new MementoCommand<Location>(*loc, &before, &after));
440 config.set_end_marker_is_free (false);
441 _have_captured = true;
444 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
445 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
446 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
448 tr->transport_stopped_wallclock (*now, xnow, abort);
452 boost::shared_ptr<RouteList> r = routes.reader ();
454 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
455 if (!(*i)->is_hidden()) {
456 (*i)->set_pending_declick (0);
461 commit_reversible_command ();
464 if (_engine.running()) {
465 update_latency_compensation (true, abort);
468 bool const auto_return_enabled =
469 (!config.get_external_sync() && config.get_auto_return());
471 if (auto_return_enabled ||
472 (ptw & PostTransportLocate) ||
473 (_requested_return_frame >= 0) ||
476 if (pending_locate_flush) {
477 flush_all_inserts ();
480 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
481 !(ptw & PostTransportLocate)) {
483 /* no explicit locate queued */
485 bool do_locate = false;
487 if (_requested_return_frame >= 0) {
489 /* explicit return request pre-queued in event list. overrides everything else */
491 cerr << "explicit auto-return to " << _requested_return_frame << endl;
493 _transport_frame = _requested_return_frame;
497 if (config.get_auto_return()) {
501 /* don't try to handle loop play when synced to JACK */
503 if (!synced_to_jack()) {
505 Location *location = _locations.auto_loop_location();
508 _transport_frame = location->start();
510 _transport_frame = _last_roll_location;
515 } else if (_play_range) {
517 /* return to start of range */
519 if (!current_audio_range.empty()) {
520 _transport_frame = current_audio_range.front().start;
526 /* regular auto-return */
528 _transport_frame = _last_roll_location;
534 _requested_return_frame = -1;
537 _engine.transport_locate (_transport_frame);
543 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
546 if (ptw & PostTransportClearSubstate) {
551 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
553 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
554 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
555 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
556 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
557 if (tr && !tr->hidden()) {
558 tr->non_realtime_locate (_transport_frame);
561 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
563 /* we will be back */
570 send_full_time_code (0);
571 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
572 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
574 if ((ptw & PostTransportLocate) && get_record_enabled()) {
575 /* capture start has been changed, so save pending state */
576 save_state ("", true);
580 /* always try to get rid of this */
582 remove_pending_capture_state ();
584 /* save the current state of things if appropriate */
586 if (did_record && !saved) {
587 save_state (_current_snapshot_name);
590 if (ptw & PostTransportDuration) {
591 DurationChanged (); /* EMIT SIGNAL */
594 if (ptw & PostTransportStop) {
599 // can't cast away volatile so copy and emit that
600 nframes64_t tframe = _transport_frame;
601 PositionChanged (tframe); /* EMIT SIGNAL */
602 TransportStateChange (); /* EMIT SIGNAL */
604 /* and start it up again if relevant */
606 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
607 request_transport_speed (1.0);
608 pending_locate_roll = false;
613 Session::check_declick_out ()
615 bool locate_required = transport_sub_state & PendingLocate;
617 /* this is called after a process() iteration. if PendingDeclickOut was set,
618 it means that we were waiting to declick the output (which has just been
619 done) before doing something else. this is where we do that "something else".
621 note: called from the audio thread.
624 if (transport_sub_state & PendingDeclickOut) {
626 if (locate_required) {
627 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
628 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
630 stop_transport (pending_abort);
631 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
637 Session::unset_play_loop ()
640 clear_events (SessionEvent::AutoLoop);
642 // set all tracks to NOT use internal looping
643 boost::shared_ptr<RouteList> rl = routes.reader ();
644 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
645 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
646 if (tr && !tr->hidden()) {
653 Session::set_play_loop (bool yn)
655 /* Called from event-handling context */
659 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
660 /* nothing to do, or can't change loop status while recording */
666 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
667 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
668 "Recommend changing the configured options"), PROGRAM_NAME)
681 if (Config->get_seamless_loop()) {
682 // set all tracks to 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 // set all tracks to NOT use internal looping
693 boost::shared_ptr<RouteList> rl = routes.reader ();
694 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
695 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
696 if (tr && !tr->hidden()) {
702 /* put the loop event into the event list */
704 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
707 /* locate to start of loop and roll. If doing seamless loop, force a
708 locate+buffer refill even if we are positioned there already.
711 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
719 TransportStateChange ();
722 Session::flush_all_inserts ()
724 boost::shared_ptr<RouteList> r = routes.reader ();
726 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
727 (*i)->flush_processors ();
732 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
734 if (synced_to_jack()) {
739 _slave->speed_and_position (sp, pos);
741 if (target_frame != pos) {
743 /* tell JACK to change transport position, and we will
744 follow along later in ::follow_slave()
747 _engine.transport_locate (target_frame);
749 if (sp != 1.0f && with_roll) {
750 _engine.transport_start ();
756 locate (target_frame, with_roll, with_flush, with_loop, force);
761 Session::micro_locate (nframes_t distance)
763 boost::shared_ptr<RouteList> rl = routes.reader();
764 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
765 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
766 if (tr && !tr->can_internal_playback_seek (distance)) {
771 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
772 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
774 tr->internal_playback_seek (distance);
778 _transport_frame += distance;
783 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
785 if (actively_recording() && !with_loop) {
789 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
791 set_transport_speed (1.0, false);
793 loop_changing = false;
797 // Update Timecode time
798 // [DR] FIXME: find out exactly where this should go below
799 _transport_frame = target_frame;
800 timecode_time(_transport_frame, transmitting_timecode_time);
801 outbound_mtc_timecode_frame = _transport_frame;
802 next_quarter_frame_to_send = 0;
804 if (_transport_speed && (!with_loop || loop_changing)) {
805 /* schedule a declick. we'll be called again when its done */
807 if (!(transport_sub_state & PendingDeclickOut)) {
808 transport_sub_state |= (PendingDeclickOut|PendingLocate);
809 pending_locate_frame = target_frame;
810 pending_locate_roll = with_roll;
811 pending_locate_flush = with_flush;
816 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
817 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
820 if (force || !with_loop || loop_changing) {
822 PostTransportWork todo = PostTransportLocate;
825 todo = PostTransportWork (todo | PostTransportRoll);
828 add_post_transport_work (todo);
829 _butler->schedule_transport_work ();
833 /* this is functionally what clear_clicks() does but with a tentative lock */
835 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
837 if (clickm.locked()) {
839 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
848 /* switch from input if we're going to roll */
849 if (Config->get_monitoring_model() == HardwareMonitoring) {
851 boost::shared_ptr<RouteList> rl = routes.reader();
852 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
853 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
854 if (tr && tr->record_enabled ()) {
855 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
856 tr->monitor_input (!config.get_auto_input());
861 /* otherwise we're going to stop, so do the opposite */
862 if (Config->get_monitoring_model() == HardwareMonitoring) {
864 boost::shared_ptr<RouteList> rl = routes.reader();
865 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
866 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
867 if (tr && tr->record_enabled ()) {
868 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
869 tr->monitor_input (true);
875 /* cancel looped playback if transport pos outside of loop range */
877 Location* al = _locations.auto_loop_location();
879 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
880 // cancel looping directly, this is called from event handling context
881 set_play_loop (false);
883 else if (al && _transport_frame == al->start()) {
885 // this is only necessary for seamless looping
887 boost::shared_ptr<RouteList> rl = routes.reader();
888 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
889 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
890 if (tr && tr->record_enabled ()) {
891 // tell it we've looped, so it can deal with the record state
892 tr->transport_looped(_transport_frame);
897 TransportLooped(); // EMIT SIGNAL
901 loop_changing = false;
903 _send_timecode_update = true;
905 Located (); /* EMIT SIGNAL */
908 /** Set the transport speed.
909 * @param speed New speed
913 Session::set_transport_speed (double speed, bool abort, bool clear_state)
915 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));
917 if (_transport_speed == speed) {
921 _target_transport_speed = fabs(speed);
923 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
924 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
928 speed = min (8.0, speed);
929 } else if (speed < 0) {
930 speed = max (-8.0, speed);
933 if (transport_rolling() && speed == 0.0) {
935 /* we are rolling and we want to stop */
937 if (Config->get_monitoring_model() == HardwareMonitoring)
939 boost::shared_ptr<RouteList> rl = routes.reader();
940 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
941 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
942 if (tr && tr->record_enabled ()) {
943 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
944 tr->monitor_input (true);
949 if (synced_to_jack ()) {
951 /* do this here because our response to the slave won't
957 _engine.transport_stop ();
959 stop_transport (abort);
962 } else if (transport_stopped() && speed == 1.0) {
964 /* we are stopped and we want to start rolling at speed 1 */
966 if (Config->get_monitoring_model() == HardwareMonitoring) {
968 boost::shared_ptr<RouteList> rl = routes.reader();
969 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
970 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
971 if (config.get_auto_input() && tr && tr->record_enabled ()) {
972 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
973 tr->monitor_input (false);
978 if (synced_to_jack()) {
979 _engine.transport_start ();
986 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
987 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
993 if (actively_recording()) {
997 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1001 if (speed < 0.0 && _transport_frame == 0) {
1007 /* if we are reversing relative to the current speed, or relative to the speed
1008 before the last stop, then we have to do extra work.
1011 PostTransportWork todo = PostTransportWork (0);
1013 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1014 todo = PostTransportWork (todo | PostTransportReverse);
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 have_looped = false;
1102 /* if record status is Enabled, move it to Recording. if its
1103 already Recording, move it to Disabled.
1106 switch (record_status()) {
1108 if (!config.get_punch_in()) {
1115 disable_record (false);
1123 transport_sub_state |= PendingDeclickIn;
1125 _transport_speed = 1.0;
1126 _target_transport_speed = 1.0;
1128 boost::shared_ptr<RouteList> rl = routes.reader();
1129 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1130 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1132 tr->realtime_set_speed (tr->speed(), true);
1136 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
1138 TransportStateChange (); /* EMIT SIGNAL */
1141 /** Do any transport work in the audio thread that needs to be done after the
1142 * transport thread is finished. Audio thread, realtime safe.
1145 Session::post_transport ()
1147 PostTransportWork ptw = post_transport_work ();
1149 if (ptw & PostTransportAudition) {
1150 if (auditioner && auditioner->auditioning()) {
1151 process_function = &Session::process_audition;
1153 process_function = &Session::process_with_events;
1157 if (ptw & PostTransportStop) {
1159 transport_sub_state = 0;
1162 if (ptw & PostTransportLocate) {
1164 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1168 transport_sub_state = 0;
1173 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1176 set_post_transport_work (PostTransportWork (0));
1180 Session::reset_rf_scale (nframes_t motion)
1182 cumulative_rf_motion += motion;
1184 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1186 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1188 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1200 Session::use_sync_source (Slave* new_slave)
1202 /* Runs in process() context */
1204 bool non_rt_required = false;
1206 /* XXX this deletion is problematic because we're in RT context */
1211 boost::shared_ptr<RouteList> rl = routes.reader();
1212 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1213 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1214 if (tr && !tr->hidden()) {
1215 if (tr->realtime_set_speed (tr->speed(), true)) {
1216 non_rt_required = true;
1218 tr->set_slaved (_slave != 0);
1222 if (non_rt_required) {
1223 add_post_transport_work (PostTransportSpeed);
1224 _butler->schedule_transport_work ();
1231 Session::drop_sync_source ()
1233 request_sync_source (0);
1237 Session::switch_to_sync_source (SyncSource src)
1241 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1245 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1251 new_slave = new MTC_Slave (*this, *_mtc_port);
1254 catch (failed_constructor& err) {
1259 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1265 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1269 if (_midi_clock_port) {
1271 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1274 catch (failed_constructor& err) {
1279 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1285 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1289 new_slave = new JACK_Slave (_engine.jack());
1297 request_sync_source (new_slave);
1301 Session::reverse_track_buffers ()
1303 add_post_transport_work (PostTransportReverse);
1304 _butler->schedule_transport_work ();
1308 Session::set_track_speed (Track* track, double speed)
1310 if (track->realtime_set_speed (speed, false)) {
1311 add_post_transport_work (PostTransportSpeed);
1312 _butler->schedule_transport_work ();
1318 Session::unset_play_range ()
1320 _play_range = false;
1321 _clear_event_type (SessionEvent::RangeStop);
1322 _clear_event_type (SessionEvent::RangeLocate);
1326 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1330 /* Called from event-processing context */
1332 unset_play_range ();
1334 if (range.empty()) {
1335 /* _play_range set to false in unset_play_range()
1337 if (!leave_rolling) {
1338 /* stop transport */
1339 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1347 /* cancel loop play */
1350 list<AudioRange>::size_type sz = range.size();
1354 list<AudioRange>::iterator i = range.begin();
1355 list<AudioRange>::iterator next;
1357 while (i != range.end()) {
1362 /* locating/stopping is subject to delays for declicking.
1365 nframes_t requested_frame = (*i).end;
1367 if (requested_frame > current_block_size) {
1368 requested_frame -= current_block_size;
1370 requested_frame = 0;
1373 if (next == range.end()) {
1374 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1376 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1384 } else if (sz == 1) {
1386 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1391 /* save range so we can do auto-return etc. */
1393 current_audio_range = range;
1395 /* now start rolling at the right place */
1397 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1400 TransportStateChange ();
1404 Session::request_bounded_roll (nframes_t start, nframes_t end)
1406 AudioRange ar (start, end, 0);
1407 list<AudioRange> lar;
1410 request_play_range (&lar, true);
1413 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1415 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1416 ev->target2_frame = start;
1421 Session::engine_halted ()
1425 /* there will be no more calls to process(), so
1426 we'd better clean up for ourselves, right now.
1428 but first, make sure the butler is out of
1432 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1433 set_post_transport_work (PostTransportWork (0));
1436 realtime_stop (false, true);
1437 non_realtime_stop (false, 0, ignored);
1438 transport_sub_state = 0;
1440 TransportStateChange (); /* EMIT SIGNAL */
1445 Session::xrun_recovery ()
1447 // can't cast away volatile so copy and emit that
1448 nframes64_t tframe = _transport_frame;
1449 Xrun (tframe); //EMIT SIGNAL
1451 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1453 /* it didn't actually halt, but we need
1454 to handle things in the same way.
1462 Session::route_processors_changed (RouteProcessorChange c)
1464 if (c.type == RouteProcessorChange::MeterPointChange) {
1468 update_latency_compensation (false, false);
1473 Session::update_latency_compensation (bool with_stop, bool abort)
1475 bool update_jack = false;
1476 PostTransportWork ptw;
1478 if (_state_of_the_state & Deletion) {
1482 _worst_track_latency = 0;
1483 ptw = post_transport_work();
1485 #undef DEBUG_LATENCY
1486 #ifdef DEBUG_LATENCY
1487 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1490 boost::shared_ptr<RouteList> r = routes.reader ();
1492 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1495 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1498 nframes_t old_latency = (*i)->output()->signal_latency ();
1499 nframes_t track_latency = (*i)->update_total_latency ();
1501 if (old_latency != track_latency) {
1502 (*i)->input()->update_port_total_latencies ();
1503 (*i)->output()->update_port_total_latencies ();
1507 if (!(*i)->is_hidden() && ((*i)->active())) {
1508 _worst_track_latency = max (_worst_track_latency, track_latency);
1513 _engine.update_total_latencies ();
1516 #ifdef DEBUG_LATENCY
1517 cerr << "\tworst was " << _worst_track_latency << endl;
1520 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1521 (*i)->set_latency_delay (_worst_track_latency);
1524 set_worst_io_latencies ();
1526 /* reflect any changes in latencies into capture offsets
1529 boost::shared_ptr<RouteList> rl = routes.reader();
1530 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1531 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1533 tr->set_capture_offset ();
1539 Session::allow_auto_play (bool yn)
1541 auto_play_legal = yn;
1545 Session::reset_jack_connection (jack_client_t* jack)
1549 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1550 js->reset_client (jack);
1555 Session::maybe_stop (nframes_t limit)
1557 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1558 if (synced_to_jack () && config.get_jack_time_master ()) {
1559 _engine.transport_stop ();
1560 } else if (!synced_to_jack ()) {