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/audio_diskstream.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_diskstream_speed (Diskstream& ds, double speed)
112 SessionEvent* ev = new SessionEvent (SessionEvent::SetDiskstreamSpeed, 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 diskstreams
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 // FIXME: where should this really be? [DR]
186 //send_full_time_code();
187 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
188 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
190 if (_transport_speed < 0.0f) {
191 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
193 todo = PostTransportWork (todo | PostTransportStop);
196 if (actively_recording()) {
198 /* move the transport position back to where the
199 request for a stop was noticed. we rolled
200 past that point to pick up delayed input.
203 decrement_transport_position (_worst_output_latency);
205 /* the duration change is not guaranteed to have happened, but is likely */
207 todo = PostTransportWork (todo | PostTransportDuration);
211 todo = PostTransportWork (todo | PostTransportAbort);
215 todo = PostTransportWork (todo | PostTransportClearSubstate);
219 add_post_transport_work (todo);
222 _clear_event_type (SessionEvent::StopOnce);
223 _clear_event_type (SessionEvent::RangeStop);
224 _clear_event_type (SessionEvent::RangeLocate);
226 disable_record (true);
228 reset_slave_state ();
230 _transport_speed = 0;
231 _target_transport_speed = 0;
233 if (config.get_use_video_sync()) {
234 waiting_for_sync_offset = true;
237 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
241 Session::butler_transport_work ()
245 PostTransportWork ptw;
246 boost::shared_ptr<RouteList> r = routes.reader ();
247 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
249 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
251 ptw = post_transport_work();
253 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
255 if (ptw & PostTransportCurveRealloc) {
256 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
257 (*i)->curve_reallocate();
261 if (ptw & PostTransportInputChange) {
262 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
263 (*i)->non_realtime_input_change ();
267 if (ptw & PostTransportSpeed) {
268 non_realtime_set_speed ();
271 if (ptw & PostTransportReverse) {
274 cumulative_rf_motion = 0;
277 /* don't seek if locate will take care of that in non_realtime_stop() */
279 if (!(ptw & PostTransportLocate)) {
281 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
282 if (!(*i)->hidden()) {
283 (*i)->non_realtime_locate (_transport_frame);
285 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
286 /* new request, stop seeking, and start again */
287 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
294 if (ptw & PostTransportLocate) {
295 non_realtime_locate ();
298 if (ptw & PostTransportStop) {
299 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
301 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
306 if (ptw & PostTransportOverWrite) {
307 non_realtime_overwrite (on_entry, finished);
309 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
314 if (ptw & PostTransportAudition) {
315 non_realtime_set_audition ();
318 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
322 Session::non_realtime_set_speed ()
324 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
326 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
327 (*i)->non_realtime_set_speed ();
332 Session::non_realtime_overwrite (int on_entry, bool& finished)
334 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
336 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
337 if ((*i)->pending_overwrite) {
338 (*i)->overwrite_existing_buffers ();
340 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
349 Session::non_realtime_locate ()
351 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
353 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
354 (*i)->non_realtime_locate (_transport_frame);
360 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
366 PostTransportWork ptw = post_transport_work();
371 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
373 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
374 if ((*i)->get_captured_frames () != 0) {
380 /* stop and locate are merged here because they share a lot of common stuff */
383 now = localtime (&xnow);
386 auditioner->cancel_audition ();
390 cumulative_rf_motion = 0;
394 begin_reversible_command ("capture");
396 Location* loc = _locations.end_location();
397 bool change_end = false;
399 if (_transport_frame < loc->end()) {
401 /* stopped recording before current end */
403 if (config.get_end_marker_is_free()) {
405 /* first capture for this session, move end back to where we are */
410 } else if (_transport_frame > loc->end()) {
412 /* stopped recording after the current end, extend it */
418 XMLNode &before = loc->get_state();
419 loc->set_end(_transport_frame);
420 XMLNode &after = loc->get_state();
421 add_command (new MementoCommand<Location>(*loc, &before, &after));
424 config.set_end_marker_is_free (false);
425 _have_captured = true;
428 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
429 (*i)->transport_stopped (*now, xnow, abort);
432 boost::shared_ptr<RouteList> r = routes.reader ();
434 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
435 if (!(*i)->is_hidden()) {
436 (*i)->set_pending_declick (0);
441 commit_reversible_command ();
444 if (_engine.running()) {
445 update_latency_compensation (true, abort);
448 bool const auto_return_enabled =
449 (!config.get_external_sync() && config.get_auto_return());
451 if (auto_return_enabled ||
452 (ptw & PostTransportLocate) ||
453 (_requested_return_frame >= 0) ||
456 if (pending_locate_flush) {
457 flush_all_inserts ();
460 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
461 !(ptw & PostTransportLocate)) {
463 /* no explicit locate queued */
465 bool do_locate = false;
467 if (_requested_return_frame >= 0) {
469 /* explicit return request pre-queued in event list. overrides everything else */
471 cerr << "explicit auto-return to " << _requested_return_frame << endl;
473 _transport_frame = _requested_return_frame;
477 if (config.get_auto_return()) {
481 /* don't try to handle loop play when synced to JACK */
483 if (!synced_to_jack()) {
485 Location *location = _locations.auto_loop_location();
488 _transport_frame = location->start();
490 _transport_frame = _last_roll_location;
495 } else if (_play_range) {
497 /* return to start of range */
499 if (!current_audio_range.empty()) {
500 _transport_frame = current_audio_range.front().start;
506 /* regular auto-return */
508 _transport_frame = _last_roll_location;
514 _requested_return_frame = -1;
517 _engine.transport_locate (_transport_frame);
523 /* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode.
526 if (ptw & PostTransportClearSubstate) {
531 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
534 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
535 if (!(*i)->hidden()) {
536 (*i)->non_realtime_locate (_transport_frame);
538 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
540 /* we will be back */
547 send_full_time_code (0);
548 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
549 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
551 if ((ptw & PostTransportLocate) && get_record_enabled()) {
552 /* capture start has been changed, so save pending state */
553 save_state ("", true);
557 /* always try to get rid of this */
559 remove_pending_capture_state ();
561 /* save the current state of things if appropriate */
563 if (did_record && !saved) {
564 save_state (_current_snapshot_name);
567 if (ptw & PostTransportDuration) {
568 DurationChanged (); /* EMIT SIGNAL */
571 if (ptw & PostTransportStop) {
576 // can't cast away volatile so copy and emit that
577 nframes64_t tframe = _transport_frame;
578 PositionChanged (tframe); /* EMIT SIGNAL */
579 TransportStateChange (); /* EMIT SIGNAL */
581 /* and start it up again if relevant */
583 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
584 request_transport_speed (1.0);
585 pending_locate_roll = false;
590 Session::check_declick_out ()
592 bool locate_required = transport_sub_state & PendingLocate;
594 /* this is called after a process() iteration. if PendingDeclickOut was set,
595 it means that we were waiting to declick the output (which has just been
596 done) before doing something else. this is where we do that "something else".
598 note: called from the audio thread.
601 if (transport_sub_state & PendingDeclickOut) {
603 if (locate_required) {
604 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
605 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
607 stop_transport (pending_abort);
608 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
614 Session::unset_play_loop ()
617 clear_events (SessionEvent::AutoLoop);
619 // set all diskstreams to NOT use internal looping
620 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
621 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
622 if (!(*i)->hidden()) {
629 Session::set_play_loop (bool yn)
631 /* Called from event-handling context */
635 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
636 /* nothing to do, or can't change loop status while recording */
642 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
643 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
644 "Recommend changing the configured options"), PROGRAM_NAME)
657 if (Config->get_seamless_loop()) {
658 // set all diskstreams to use internal looping
659 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
660 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
661 if (!(*i)->hidden()) {
662 (*i)->set_loop (loc);
667 // set all diskstreams to NOT use internal looping
668 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
669 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
670 if (!(*i)->hidden()) {
676 /* put the loop event into the event list */
678 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
681 /* locate to start of loop and roll. If doing seamless loop, force a
682 locate+buffer refill even if we are positioned there already.
685 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
693 TransportStateChange ();
696 Session::flush_all_inserts ()
698 boost::shared_ptr<RouteList> r = routes.reader ();
700 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
701 (*i)->flush_processors ();
706 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
708 if (synced_to_jack()) {
713 _slave->speed_and_position (sp, pos);
715 if (target_frame != pos) {
717 /* tell JACK to change transport position, and we will
718 follow along later in ::follow_slave()
721 _engine.transport_locate (target_frame);
723 if (sp != 1.0f && with_roll) {
724 _engine.transport_start ();
730 locate (target_frame, with_roll, with_flush, with_loop, force);
735 Session::micro_locate (nframes_t distance)
737 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
739 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
740 if (!(*i)->can_internal_playback_seek (distance)) {
745 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
746 (*i)->internal_playback_seek (distance);
749 _transport_frame += distance;
754 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
756 if (actively_recording() && !with_loop) {
760 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
762 set_transport_speed (1.0, false);
764 loop_changing = false;
768 // Update Timecode time
769 // [DR] FIXME: find out exactly where this should go below
770 _transport_frame = target_frame;
771 timecode_time(_transport_frame, transmitting_timecode_time);
772 outbound_mtc_timecode_frame = _transport_frame;
773 next_quarter_frame_to_send = 0;
775 if (_transport_speed && (!with_loop || loop_changing)) {
776 /* schedule a declick. we'll be called again when its done */
778 if (!(transport_sub_state & PendingDeclickOut)) {
779 transport_sub_state |= (PendingDeclickOut|PendingLocate);
780 pending_locate_frame = target_frame;
781 pending_locate_roll = with_roll;
782 pending_locate_flush = with_flush;
787 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
788 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
791 if (force || !with_loop || loop_changing) {
793 PostTransportWork todo = PostTransportLocate;
796 todo = PostTransportWork (todo | PostTransportRoll);
799 add_post_transport_work (todo);
800 _butler->schedule_transport_work ();
804 /* this is functionally what clear_clicks() does but with a tentative lock */
806 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
808 if (clickm.locked()) {
810 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
819 /* switch from input if we're going to roll */
820 if (Config->get_monitoring_model() == HardwareMonitoring) {
822 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
824 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
825 if ((*i)->record_enabled ()) {
826 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
827 (*i)->monitor_input (!config.get_auto_input());
832 /* otherwise we're going to stop, so do the opposite */
833 if (Config->get_monitoring_model() == HardwareMonitoring) {
834 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
836 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
837 if ((*i)->record_enabled ()) {
838 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
839 (*i)->monitor_input (true);
845 /* cancel looped playback if transport pos outside of loop range */
847 Location* al = _locations.auto_loop_location();
849 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
850 // cancel looping directly, this is called from event handling context
851 set_play_loop (false);
853 else if (al && _transport_frame == al->start()) {
855 // this is only necessary for seamless looping
857 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
859 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
860 if ((*i)->record_enabled ()) {
861 // tell it we've looped, so it can deal with the record state
862 (*i)->transport_looped(_transport_frame);
867 TransportLooped(); // EMIT SIGNAL
871 loop_changing = false;
873 _send_timecode_update = true;
875 Located (); /* EMIT SIGNAL */
878 /** Set the transport speed.
879 * @param speed New speed
883 Session::set_transport_speed (double speed, bool abort, bool clear_state)
885 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));
887 if (_transport_speed == speed) {
891 _target_transport_speed = fabs(speed);
893 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
894 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
898 speed = min (8.0, speed);
899 } else if (speed < 0) {
900 speed = max (-8.0, speed);
903 if (transport_rolling() && speed == 0.0) {
905 /* we are rolling and we want to stop */
907 if (Config->get_monitoring_model() == HardwareMonitoring)
909 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
911 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
912 if ((*i)->record_enabled ()) {
913 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
914 (*i)->monitor_input (true);
919 if (synced_to_jack ()) {
921 /* do this here because our response to the slave won't
927 _engine.transport_stop ();
929 stop_transport (abort);
932 } else if (transport_stopped() && speed == 1.0) {
934 /* we are stopped and we want to start rolling at speed 1 */
936 if (Config->get_monitoring_model() == HardwareMonitoring) {
938 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
940 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
941 if (config.get_auto_input() && (*i)->record_enabled ()) {
942 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
943 (*i)->monitor_input (false);
948 if (synced_to_jack()) {
949 _engine.transport_start ();
956 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
957 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
963 if (actively_recording()) {
967 if (speed > 0.0 && _transport_frame == current_end_frame()) {
971 if (speed < 0.0 && _transport_frame == 0) {
977 /* if we are reversing relative to the current speed, or relative to the speed
978 before the last stop, then we have to do extra work.
981 PostTransportWork todo = PostTransportWork (0);
983 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
984 todo = PostTransportWork (todo | PostTransportReverse);
987 _last_transport_speed = _transport_speed;
988 _transport_speed = speed;
990 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
991 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
992 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
993 todo = PostTransportWork (todo | PostTransportSpeed);
999 add_post_transport_work (todo);
1000 _butler->schedule_transport_work ();
1006 /** Stop the transport. */
1008 Session::stop_transport (bool abort, bool clear_state)
1010 if (_transport_speed == 0.0f) {
1014 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
1015 _worst_output_latency > current_block_size)
1018 /* we need to capture the audio that has still not yet been received by the system
1019 at the time the stop is requested, so we have to roll past that time.
1021 we want to declick before stopping, so schedule the autostop for one
1022 block before the actual end. we'll declick in the subsequent block,
1023 and then we'll really be stopped.
1026 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1027 _transport_frame + _worst_output_latency - current_block_size,
1031 transport_sub_state |= StopPendingCapture;
1032 pending_abort = abort;
1037 if ((transport_sub_state & PendingDeclickOut) == 0) {
1038 transport_sub_state |= PendingDeclickOut;
1039 /* we'll be called again after the declick */
1040 pending_abort = abort;
1044 realtime_stop (abort, clear_state);
1045 _butler->schedule_transport_work ();
1049 Session::start_transport ()
1051 _last_roll_location = _transport_frame;
1052 have_looped = false;
1054 /* if record status is Enabled, move it to Recording. if its
1055 already Recording, move it to Disabled.
1058 switch (record_status()) {
1060 if (!config.get_punch_in()) {
1067 disable_record (false);
1075 transport_sub_state |= PendingDeclickIn;
1077 _transport_speed = 1.0;
1078 _target_transport_speed = 1.0;
1080 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1081 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1082 (*i)->realtime_set_speed ((*i)->speed(), true);
1085 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
1087 TransportStateChange (); /* EMIT SIGNAL */
1090 /** Do any transport work in the audio thread that needs to be done after the
1091 * transport thread is finished. Audio thread, realtime safe.
1094 Session::post_transport ()
1096 PostTransportWork ptw = post_transport_work ();
1098 if (ptw & PostTransportAudition) {
1099 if (auditioner && auditioner->auditioning()) {
1100 process_function = &Session::process_audition;
1102 process_function = &Session::process_with_events;
1106 if (ptw & PostTransportStop) {
1108 transport_sub_state = 0;
1111 if (ptw & PostTransportLocate) {
1113 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1117 transport_sub_state = 0;
1122 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1125 set_post_transport_work (PostTransportWork (0));
1129 Session::reset_rf_scale (nframes_t motion)
1131 cumulative_rf_motion += motion;
1133 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1135 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1137 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1149 Session::use_sync_source (Slave* new_slave)
1151 /* Runs in process() context */
1153 bool non_rt_required = false;
1155 /* XXX this deletion is problematic because we're in RT context */
1160 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1161 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1162 if (!(*i)->hidden()) {
1163 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1164 non_rt_required = true;
1166 (*i)->set_slaved (_slave != 0);
1170 if (non_rt_required) {
1171 add_post_transport_work (PostTransportSpeed);
1172 _butler->schedule_transport_work ();
1179 Session::drop_sync_source ()
1181 request_sync_source (0);
1185 Session::switch_to_sync_source (SyncSource src)
1189 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1193 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1199 new_slave = new MTC_Slave (*this, *_mtc_port);
1202 catch (failed_constructor& err) {
1207 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1213 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1217 if (_midi_clock_port) {
1219 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1222 catch (failed_constructor& err) {
1227 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1233 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1237 new_slave = new JACK_Slave (_engine.jack());
1245 request_sync_source (new_slave);
1249 Session::reverse_diskstream_buffers ()
1251 add_post_transport_work (PostTransportReverse);
1252 _butler->schedule_transport_work ();
1256 Session::set_diskstream_speed (Diskstream* stream, double speed)
1258 if (stream->realtime_set_speed (speed, false)) {
1259 add_post_transport_work (PostTransportSpeed);
1260 _butler->schedule_transport_work ();
1266 Session::unset_play_range ()
1268 _play_range = false;
1269 _clear_event_type (SessionEvent::RangeStop);
1270 _clear_event_type (SessionEvent::RangeLocate);
1274 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1278 /* Called from event-processing context */
1280 unset_play_range ();
1282 if (range.empty()) {
1283 /* _play_range set to false in unset_play_range()
1285 if (!leave_rolling) {
1286 /* stop transport */
1287 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1295 /* cancel loop play */
1298 list<AudioRange>::size_type sz = range.size();
1302 list<AudioRange>::iterator i = range.begin();
1303 list<AudioRange>::iterator next;
1305 while (i != range.end()) {
1310 /* locating/stopping is subject to delays for declicking.
1313 nframes_t requested_frame = (*i).end;
1315 if (requested_frame > current_block_size) {
1316 requested_frame -= current_block_size;
1318 requested_frame = 0;
1321 if (next == range.end()) {
1322 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1324 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1332 } else if (sz == 1) {
1334 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1339 /* save range so we can do auto-return etc. */
1341 current_audio_range = range;
1343 /* now start rolling at the right place */
1345 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1348 TransportStateChange ();
1352 Session::request_bounded_roll (nframes_t start, nframes_t end)
1354 AudioRange ar (start, end, 0);
1355 list<AudioRange> lar;
1358 request_play_range (&lar, true);
1361 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1363 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1364 ev->target2_frame = start;
1369 Session::engine_halted ()
1373 /* there will be no more calls to process(), so
1374 we'd better clean up for ourselves, right now.
1376 but first, make sure the butler is out of
1380 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1381 set_post_transport_work (PostTransportWork (0));
1384 realtime_stop (false, true);
1385 non_realtime_stop (false, 0, ignored);
1386 transport_sub_state = 0;
1388 TransportStateChange (); /* EMIT SIGNAL */
1393 Session::xrun_recovery ()
1395 // can't cast away volatile so copy and emit that
1396 nframes64_t tframe = _transport_frame;
1397 Xrun (tframe); //EMIT SIGNAL
1399 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1401 /* it didn't actually halt, but we need
1402 to handle things in the same way.
1410 Session::route_processors_changed (RouteProcessorChange c)
1412 if (c.type == RouteProcessorChange::MeterPointChange) {
1416 update_latency_compensation (false, false);
1420 Session::update_latency_compensation (bool with_stop, bool abort)
1422 bool update_jack = false;
1423 PostTransportWork ptw;
1425 if (_state_of_the_state & Deletion) {
1429 _worst_track_latency = 0;
1430 ptw = post_transport_work();
1432 #undef DEBUG_LATENCY
1433 #ifdef DEBUG_LATENCY
1434 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1437 boost::shared_ptr<RouteList> r = routes.reader ();
1439 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1442 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1445 nframes_t old_latency = (*i)->output()->signal_latency ();
1446 nframes_t track_latency = (*i)->update_total_latency ();
1448 if (old_latency != track_latency) {
1449 (*i)->input()->update_port_total_latencies ();
1450 (*i)->output()->update_port_total_latencies ();
1454 if (!(*i)->is_hidden() && ((*i)->active())) {
1455 _worst_track_latency = max (_worst_track_latency, track_latency);
1460 _engine.update_total_latencies ();
1463 #ifdef DEBUG_LATENCY
1464 cerr << "\tworst was " << _worst_track_latency << endl;
1467 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1468 (*i)->set_latency_delay (_worst_track_latency);
1471 set_worst_io_latencies ();
1473 /* reflect any changes in latencies into capture offsets
1476 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1478 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1479 (*i)->set_capture_offset ();
1484 Session::allow_auto_play (bool yn)
1486 auto_play_legal = yn;
1490 Session::reset_jack_connection (jack_client_t* jack)
1494 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1495 js->reset_client (jack);
1500 Session::maybe_stop (nframes_t limit)
1502 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1503 if (synced_to_jack () && config.get_jack_time_master ()) {
1504 _engine.transport_stop ();
1505 } else if (!synced_to_jack ()) {