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 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
188 timecode_time_subframes (_transport_frame, time);
189 _mmc->send (MIDI::MachineControlCommand (time));
191 if (_transport_speed < 0.0f) {
192 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
194 todo = PostTransportWork (todo | PostTransportStop);
197 if (actively_recording()) {
199 /* move the transport position back to where the
200 request for a stop was noticed. we rolled
201 past that point to pick up delayed input (and/or to delick)
204 if (_worst_output_latency > current_block_size) {
205 /* we rolled past the stop point to pick up data that had
206 not yet arrived. move back to where the stop occured.
208 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
210 decrement_transport_position (current_block_size);
213 /* the duration change is not guaranteed to have happened, but is likely */
215 todo = PostTransportWork (todo | PostTransportDuration);
219 todo = PostTransportWork (todo | PostTransportAbort);
223 todo = PostTransportWork (todo | PostTransportClearSubstate);
227 add_post_transport_work (todo);
230 _clear_event_type (SessionEvent::StopOnce);
231 _clear_event_type (SessionEvent::RangeStop);
232 _clear_event_type (SessionEvent::RangeLocate);
234 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
235 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
237 reset_slave_state ();
239 _transport_speed = 0;
240 _target_transport_speed = 0;
242 g_atomic_int_set (&_playback_load, 100);
243 g_atomic_int_set (&_capture_load, 100);
245 if (config.get_use_video_sync()) {
246 waiting_for_sync_offset = true;
249 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
253 Session::butler_transport_work ()
257 PostTransportWork ptw;
258 boost::shared_ptr<RouteList> r = routes.reader ();
260 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
262 ptw = post_transport_work();
264 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
266 if (ptw & PostTransportAdjustPlaybackBuffering) {
267 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
268 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
270 tr->adjust_playback_buffering ();
271 /* and refill those buffers ... */
272 tr->non_realtime_locate (_transport_frame);
278 if (ptw & PostTransportAdjustCaptureBuffering) {
279 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
280 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
282 tr->adjust_capture_buffering ();
287 if (ptw & PostTransportCurveRealloc) {
288 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
289 (*i)->curve_reallocate();
293 if (ptw & PostTransportInputChange) {
294 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
295 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
297 tr->non_realtime_input_change ();
302 if (ptw & PostTransportSpeed) {
303 non_realtime_set_speed ();
306 if (ptw & PostTransportReverse) {
309 cumulative_rf_motion = 0;
312 /* don't seek if locate will take care of that in non_realtime_stop() */
314 if (!(ptw & PostTransportLocate)) {
316 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
317 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
318 if (tr && !tr->hidden()) {
319 tr->non_realtime_locate (_transport_frame);
321 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
322 /* new request, stop seeking, and start again */
323 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
330 if (ptw & PostTransportLocate) {
331 non_realtime_locate ();
334 if (ptw & PostTransportStop) {
335 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
337 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
342 if (ptw & PostTransportOverWrite) {
343 non_realtime_overwrite (on_entry, finished);
345 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
350 if (ptw & PostTransportAudition) {
351 non_realtime_set_audition ();
354 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
356 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
360 Session::non_realtime_set_speed ()
362 boost::shared_ptr<RouteList> rl = routes.reader();
363 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
364 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
366 tr->non_realtime_set_speed ();
372 Session::non_realtime_overwrite (int on_entry, bool& finished)
374 boost::shared_ptr<RouteList> rl = routes.reader();
375 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
376 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
377 if (tr && tr->pending_overwrite ()) {
378 tr->overwrite_existing_buffers ();
380 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
389 Session::non_realtime_locate ()
391 boost::shared_ptr<RouteList> rl = routes.reader();
392 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
393 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
395 tr->non_realtime_locate (_transport_frame);
402 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
408 PostTransportWork ptw = post_transport_work();
413 boost::shared_ptr<RouteList> rl = routes.reader();
414 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
415 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
416 if (tr && tr->get_captured_frames () != 0) {
422 /* stop and locate are merged here because they share a lot of common stuff */
425 now = localtime (&xnow);
428 auditioner->cancel_audition ();
432 cumulative_rf_motion = 0;
436 begin_reversible_command ("capture");
437 _have_captured = true;
440 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
441 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
442 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
444 tr->transport_stopped_wallclock (*now, xnow, abort);
448 boost::shared_ptr<RouteList> r = routes.reader ();
450 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
451 if (!(*i)->is_hidden()) {
452 (*i)->set_pending_declick (0);
457 commit_reversible_command ();
460 if (_engine.running()) {
461 update_latency_compensation (true, abort);
464 bool const auto_return_enabled =
465 (!config.get_external_sync() && config.get_auto_return());
467 if (auto_return_enabled ||
468 (ptw & PostTransportLocate) ||
469 (_requested_return_frame >= 0) ||
472 if (pending_locate_flush) {
473 flush_all_inserts ();
476 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
477 !(ptw & PostTransportLocate)) {
479 /* no explicit locate queued */
481 bool do_locate = false;
483 if (_requested_return_frame >= 0) {
485 /* explicit return request pre-queued in event list. overrides everything else */
487 cerr << "explicit auto-return to " << _requested_return_frame << endl;
489 _transport_frame = _requested_return_frame;
493 if (config.get_auto_return()) {
497 /* don't try to handle loop play when synced to JACK */
499 if (!synced_to_jack()) {
501 Location *location = _locations.auto_loop_location();
504 _transport_frame = location->start();
506 _transport_frame = _last_roll_location;
511 } else if (_play_range) {
513 /* return to start of range */
515 if (!current_audio_range.empty()) {
516 _transport_frame = current_audio_range.front().start;
522 /* regular auto-return */
524 _transport_frame = _last_roll_location;
530 _requested_return_frame = -1;
533 _engine.transport_locate (_transport_frame);
539 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
542 if (ptw & PostTransportClearSubstate) {
547 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
549 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
550 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
551 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
552 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
553 if (tr && !tr->hidden()) {
554 tr->non_realtime_locate (_transport_frame);
557 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
559 /* we will be back */
566 send_full_time_code (0);
568 if ((ptw & PostTransportLocate) && get_record_enabled()) {
569 /* capture start has been changed, so save pending state */
570 save_state ("", true);
574 /* always try to get rid of this */
576 remove_pending_capture_state ();
578 /* save the current state of things if appropriate */
580 if (did_record && !saved) {
581 save_state (_current_snapshot_name);
584 if (ptw & PostTransportStop) {
589 // can't cast away volatile so copy and emit that
590 nframes64_t tframe = _transport_frame;
591 PositionChanged (tframe); /* EMIT SIGNAL */
592 TransportStateChange (); /* EMIT SIGNAL */
594 /* and start it up again if relevant */
596 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
597 request_transport_speed (1.0);
598 pending_locate_roll = false;
603 Session::check_declick_out ()
605 bool locate_required = transport_sub_state & PendingLocate;
607 /* this is called after a process() iteration. if PendingDeclickOut was set,
608 it means that we were waiting to declick the output (which has just been
609 done) before doing something else. this is where we do that "something else".
611 note: called from the audio thread.
614 if (transport_sub_state & PendingDeclickOut) {
616 if (locate_required) {
617 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
618 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
620 stop_transport (pending_abort);
621 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
627 Session::unset_play_loop ()
630 clear_events (SessionEvent::AutoLoop);
632 // set all tracks to NOT use internal looping
633 boost::shared_ptr<RouteList> rl = routes.reader ();
634 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
635 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
636 if (tr && !tr->hidden()) {
643 Session::set_play_loop (bool yn)
645 /* Called from event-handling context */
649 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
650 /* nothing to do, or can't change loop status while recording */
656 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
657 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
658 "Recommend changing the configured options"), PROGRAM_NAME)
671 if (Config->get_seamless_loop()) {
672 // set all tracks to use internal looping
673 boost::shared_ptr<RouteList> rl = routes.reader ();
674 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
675 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
676 if (tr && !tr->hidden()) {
682 // set all tracks to NOT use internal looping
683 boost::shared_ptr<RouteList> rl = routes.reader ();
684 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
685 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
686 if (tr && !tr->hidden()) {
692 /* put the loop event into the event list */
694 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
697 /* locate to start of loop and roll. If doing seamless loop, force a
698 locate+buffer refill even if we are positioned there already.
701 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
709 TransportStateChange ();
712 Session::flush_all_inserts ()
714 boost::shared_ptr<RouteList> r = routes.reader ();
716 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
717 (*i)->flush_processors ();
722 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
724 if (synced_to_jack()) {
729 _slave->speed_and_position (sp, pos);
731 if (target_frame != pos) {
733 /* tell JACK to change transport position, and we will
734 follow along later in ::follow_slave()
737 _engine.transport_locate (target_frame);
739 if (sp != 1.0f && with_roll) {
740 _engine.transport_start ();
746 locate (target_frame, with_roll, with_flush, with_loop, force);
751 Session::micro_locate (nframes_t distance)
753 boost::shared_ptr<RouteList> rl = routes.reader();
754 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
755 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
756 if (tr && !tr->can_internal_playback_seek (distance)) {
761 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
762 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
764 tr->internal_playback_seek (distance);
768 _transport_frame += distance;
772 /** @param with_mmc true to send a MMC locate command when the locate is done */
774 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
776 if (actively_recording() && !with_loop) {
780 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
782 set_transport_speed (1.0, false);
784 loop_changing = false;
788 // Update Timecode time
789 // [DR] FIXME: find out exactly where this should go below
790 _transport_frame = target_frame;
791 timecode_time(_transport_frame, transmitting_timecode_time);
792 outbound_mtc_timecode_frame = _transport_frame;
793 next_quarter_frame_to_send = 0;
795 if (_transport_speed && (!with_loop || loop_changing)) {
796 /* schedule a declick. we'll be called again when its done */
798 if (!(transport_sub_state & PendingDeclickOut)) {
799 transport_sub_state |= (PendingDeclickOut|PendingLocate);
800 pending_locate_frame = target_frame;
801 pending_locate_roll = with_roll;
802 pending_locate_flush = with_flush;
807 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
808 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
811 if (force || !with_loop || loop_changing) {
813 PostTransportWork todo = PostTransportLocate;
816 todo = PostTransportWork (todo | PostTransportRoll);
819 add_post_transport_work (todo);
820 _butler->schedule_transport_work ();
824 /* this is functionally what clear_clicks() does but with a tentative lock */
826 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
828 if (clickm.locked()) {
830 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
839 /* switch from input if we're going to roll */
840 if (Config->get_monitoring_model() == HardwareMonitoring) {
842 boost::shared_ptr<RouteList> rl = routes.reader();
843 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
844 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
845 if (tr && tr->record_enabled ()) {
846 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
847 tr->monitor_input (!config.get_auto_input());
852 /* otherwise we're going to stop, so do the opposite */
853 if (Config->get_monitoring_model() == HardwareMonitoring) {
855 boost::shared_ptr<RouteList> rl = routes.reader();
856 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
857 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
858 if (tr && tr->record_enabled ()) {
859 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
860 tr->monitor_input (true);
866 /* cancel looped playback if transport pos outside of loop range */
868 Location* al = _locations.auto_loop_location();
870 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
871 // cancel looping directly, this is called from event handling context
872 set_play_loop (false);
874 else if (al && _transport_frame == al->start()) {
876 // this is only necessary for seamless looping
878 boost::shared_ptr<RouteList> rl = routes.reader();
879 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
880 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
881 if (tr && tr->record_enabled ()) {
882 // tell it we've looped, so it can deal with the record state
883 tr->transport_looped(_transport_frame);
888 TransportLooped(); // EMIT SIGNAL
892 loop_changing = false;
894 _send_timecode_update = true;
898 timecode_time_subframes (_transport_frame, time);
899 _mmc->send (MIDI::MachineControlCommand (time));
902 Located (); /* EMIT SIGNAL */
905 /** Set the transport speed.
906 * @param speed New speed
910 Session::set_transport_speed (double speed, bool abort, bool clear_state)
912 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));
914 if (_transport_speed == speed) {
918 _target_transport_speed = fabs(speed);
920 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
921 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
925 speed = min (8.0, speed);
926 } else if (speed < 0) {
927 speed = max (-8.0, speed);
930 if (transport_rolling() && speed == 0.0) {
932 /* we are rolling and we want to stop */
934 if (Config->get_monitoring_model() == HardwareMonitoring)
936 boost::shared_ptr<RouteList> rl = routes.reader();
937 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
938 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
939 if (tr && tr->record_enabled ()) {
940 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
941 tr->monitor_input (true);
946 if (synced_to_jack ()) {
948 /* do this here because our response to the slave won't
954 _engine.transport_stop ();
956 stop_transport (abort);
959 } else if (transport_stopped() && speed == 1.0) {
961 /* we are stopped and we want to start rolling at speed 1 */
963 if (Config->get_monitoring_model() == HardwareMonitoring) {
965 boost::shared_ptr<RouteList> rl = routes.reader();
966 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
967 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
968 if (config.get_auto_input() && tr && tr->record_enabled ()) {
969 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
970 tr->monitor_input (false);
975 if (synced_to_jack()) {
976 _engine.transport_start ();
983 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
984 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
990 if (actively_recording()) {
994 if (speed > 0.0 && _transport_frame == current_end_frame()) {
998 if (speed < 0.0 && _transport_frame == 0) {
1004 /* if we are reversing relative to the current speed, or relative to the speed
1005 before the last stop, then we have to do extra work.
1008 PostTransportWork todo = PostTransportWork (0);
1010 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1011 todo = PostTransportWork (todo | PostTransportReverse);
1012 _last_roll_or_reversal_location = _transport_frame;
1015 _last_transport_speed = _transport_speed;
1016 _transport_speed = speed;
1018 boost::shared_ptr<RouteList> rl = routes.reader();
1019 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1020 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1021 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1022 todo = PostTransportWork (todo | PostTransportSpeed);
1028 add_post_transport_work (todo);
1029 _butler->schedule_transport_work ();
1035 /** Stop the transport. */
1037 Session::stop_transport (bool abort, bool clear_state)
1039 if (_transport_speed == 0.0f) {
1043 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1045 boost::shared_ptr<RouteList> rl = routes.reader();
1046 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1047 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1049 tr->prepare_to_stop (_transport_frame);
1053 /* we need to capture the audio that has still not yet been received by the system
1054 at the time the stop is requested, so we have to roll past that time.
1056 we want to declick before stopping, so schedule the autostop for one
1057 block before the actual end. we'll declick in the subsequent block,
1058 and then we'll really be stopped.
1061 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1062 _transport_frame + _worst_output_latency - current_block_size,
1066 transport_sub_state |= StopPendingCapture;
1067 pending_abort = abort;
1072 if ((transport_sub_state & PendingDeclickOut) == 0) {
1074 if (!(transport_sub_state & StopPendingCapture)) {
1075 boost::shared_ptr<RouteList> rl = routes.reader();
1076 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1077 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1079 tr->prepare_to_stop (_transport_frame);
1084 transport_sub_state |= PendingDeclickOut;
1085 /* we'll be called again after the declick */
1086 pending_abort = abort;
1090 realtime_stop (abort, clear_state);
1091 _butler->schedule_transport_work ();
1095 Session::start_transport ()
1097 _last_roll_location = _transport_frame;
1098 _last_roll_or_reversal_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 Timecode::Time time;
1137 timecode_time_subframes (_transport_frame, time);
1138 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1140 TransportStateChange (); /* EMIT SIGNAL */
1143 /** Do any transport work in the audio thread that needs to be done after the
1144 * transport thread is finished. Audio thread, realtime safe.
1147 Session::post_transport ()
1149 PostTransportWork ptw = post_transport_work ();
1151 if (ptw & PostTransportAudition) {
1152 if (auditioner && auditioner->auditioning()) {
1153 process_function = &Session::process_audition;
1155 process_function = &Session::process_with_events;
1159 if (ptw & PostTransportStop) {
1161 transport_sub_state = 0;
1164 if (ptw & PostTransportLocate) {
1166 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1170 transport_sub_state = 0;
1175 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1178 set_post_transport_work (PostTransportWork (0));
1182 Session::reset_rf_scale (nframes_t motion)
1184 cumulative_rf_motion += motion;
1186 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1188 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1190 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1202 Session::use_sync_source (Slave* new_slave)
1204 /* Runs in process() context */
1206 bool non_rt_required = false;
1208 /* XXX this deletion is problematic because we're in RT context */
1213 boost::shared_ptr<RouteList> rl = routes.reader();
1214 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1215 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1216 if (tr && !tr->hidden()) {
1217 if (tr->realtime_set_speed (tr->speed(), true)) {
1218 non_rt_required = true;
1220 tr->set_slaved (_slave != 0);
1224 if (non_rt_required) {
1225 add_post_transport_work (PostTransportSpeed);
1226 _butler->schedule_transport_work ();
1233 Session::drop_sync_source ()
1235 request_sync_source (0);
1239 Session::switch_to_sync_source (SyncSource src)
1243 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1247 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1253 new_slave = new MTC_Slave (*this, *_mtc_port);
1256 catch (failed_constructor& err) {
1261 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1267 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1271 if (_midi_clock_port) {
1273 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1276 catch (failed_constructor& err) {
1281 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1287 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1291 new_slave = new JACK_Slave (_engine.jack());
1299 request_sync_source (new_slave);
1303 Session::reverse_track_buffers ()
1305 add_post_transport_work (PostTransportReverse);
1306 _butler->schedule_transport_work ();
1310 Session::set_track_speed (Track* track, double speed)
1312 if (track->realtime_set_speed (speed, false)) {
1313 add_post_transport_work (PostTransportSpeed);
1314 _butler->schedule_transport_work ();
1320 Session::unset_play_range ()
1322 _play_range = false;
1323 _clear_event_type (SessionEvent::RangeStop);
1324 _clear_event_type (SessionEvent::RangeLocate);
1328 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1332 /* Called from event-processing context */
1334 unset_play_range ();
1336 if (range.empty()) {
1337 /* _play_range set to false in unset_play_range()
1339 if (!leave_rolling) {
1340 /* stop transport */
1341 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1349 /* cancel loop play */
1352 list<AudioRange>::size_type sz = range.size();
1356 list<AudioRange>::iterator i = range.begin();
1357 list<AudioRange>::iterator next;
1359 while (i != range.end()) {
1364 /* locating/stopping is subject to delays for declicking.
1367 nframes_t requested_frame = (*i).end;
1369 if (requested_frame > current_block_size) {
1370 requested_frame -= current_block_size;
1372 requested_frame = 0;
1375 if (next == range.end()) {
1376 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1378 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1386 } else if (sz == 1) {
1388 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1393 /* save range so we can do auto-return etc. */
1395 current_audio_range = range;
1397 /* now start rolling at the right place */
1399 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1402 TransportStateChange ();
1406 Session::request_bounded_roll (nframes_t start, nframes_t end)
1408 AudioRange ar (start, end, 0);
1409 list<AudioRange> lar;
1412 request_play_range (&lar, true);
1415 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1417 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1418 ev->target2_frame = start;
1423 Session::engine_halted ()
1427 /* there will be no more calls to process(), so
1428 we'd better clean up for ourselves, right now.
1430 but first, make sure the butler is out of
1434 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1435 set_post_transport_work (PostTransportWork (0));
1438 realtime_stop (false, true);
1439 non_realtime_stop (false, 0, ignored);
1440 transport_sub_state = 0;
1442 TransportStateChange (); /* EMIT SIGNAL */
1447 Session::xrun_recovery ()
1449 // can't cast away volatile so copy and emit that
1450 nframes64_t tframe = _transport_frame;
1451 Xrun (tframe); //EMIT SIGNAL
1453 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1455 /* it didn't actually halt, but we need
1456 to handle things in the same way.
1464 Session::route_processors_changed (RouteProcessorChange c)
1466 if (c.type == RouteProcessorChange::MeterPointChange) {
1470 update_latency_compensation (false, false);
1475 Session::update_latency_compensation (bool with_stop, bool abort)
1477 bool update_jack = false;
1478 PostTransportWork ptw;
1480 if (_state_of_the_state & Deletion) {
1484 _worst_track_latency = 0;
1485 ptw = post_transport_work();
1487 #undef DEBUG_LATENCY
1488 #ifdef DEBUG_LATENCY
1489 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1492 boost::shared_ptr<RouteList> r = routes.reader ();
1494 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1497 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1500 nframes_t old_latency = (*i)->output()->signal_latency ();
1501 nframes_t track_latency = (*i)->update_total_latency ();
1503 if (old_latency != track_latency) {
1504 (*i)->input()->update_port_total_latencies ();
1505 (*i)->output()->update_port_total_latencies ();
1509 if (!(*i)->is_hidden() && ((*i)->active())) {
1510 _worst_track_latency = max (_worst_track_latency, track_latency);
1515 _engine.update_total_latencies ();
1518 #ifdef DEBUG_LATENCY
1519 cerr << "\tworst was " << _worst_track_latency << endl;
1522 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1523 (*i)->set_latency_delay (_worst_track_latency);
1526 set_worst_io_latencies ();
1528 /* reflect any changes in latencies into capture offsets
1531 boost::shared_ptr<RouteList> rl = routes.reader();
1532 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1533 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1535 tr->set_capture_offset ();
1541 Session::allow_auto_play (bool yn)
1543 auto_play_legal = yn;
1547 Session::reset_jack_connection (jack_client_t* jack)
1551 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1552 js->reset_client (jack);
1557 Session::maybe_stop (nframes_t limit)
1559 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1560 if (synced_to_jack () && config.get_jack_time_master ()) {
1561 _engine.transport_stop ();
1562 } else if (!synced_to_jack ()) {