2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "pbd/error.h"
27 #include "pbd/enumwriter.h"
28 #include "pbd/pthread_utils.h"
29 #include "pbd/memento_command.h"
31 #include "midi++/mmc.h"
32 #include "midi++/port.h"
34 #include "ardour/ardour.h"
35 #include "ardour/audioengine.h"
36 #include "ardour/auditioner.h"
37 #include "ardour/butler.h"
38 #include "ardour/debug.h"
39 #include "ardour/location.h"
40 #include "ardour/session.h"
41 #include "ardour/slave.h"
46 using namespace ARDOUR;
50 Session::add_post_transport_work (PostTransportWork ptw)
52 PostTransportWork oldval;
53 PostTransportWork newval;
57 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
58 newval = PostTransportWork (oldval | ptw);
59 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
65 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
69 Session::request_input_change_handling ()
71 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
72 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
78 Session::request_sync_source (Slave* new_slave)
80 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
83 seamless = Config->get_seamless_loop ();
85 if (dynamic_cast<JACK_Slave*>(new_slave)) {
86 /* JACK cannot support seamless looping at present */
87 Config->set_seamless_loop (false);
89 /* reset to whatever the value was before we last switched slaves */
90 Config->set_seamless_loop (_was_seamless);
93 /* save value of seamless from before the switch */
94 _was_seamless = seamless;
96 ev->slave = new_slave;
101 Session::request_transport_speed (double speed)
103 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
104 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
109 Session::request_track_speed (Track* tr, double speed)
111 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
117 Session::request_stop (bool abort, bool clear_state)
119 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
120 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
125 Session::request_locate (nframes_t target_frame, bool with_roll)
127 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
128 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
133 Session::force_locate (nframes64_t target_frame, bool with_roll)
135 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
136 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
141 Session::request_play_loop (bool yn, bool leave_rolling)
144 Location *location = _locations.auto_loop_location();
146 if (location == 0 && yn) {
147 error << _("Cannot loop - no loop range defined")
152 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
153 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
156 if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
157 // request an immediate locate to refresh the tracks
158 // after disabling looping
159 request_locate (_transport_frame-1, false);
164 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
166 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
168 ev->audio_range = *range;
170 ev->audio_range.clear ();
172 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
177 Session::realtime_stop (bool abort, bool clear_state)
179 DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
180 PostTransportWork todo = PostTransportWork (0);
182 /* assume that when we start, we'll be moving forwards */
184 // FIXME: where should this really be? [DR]
185 //send_full_time_code();
187 timecode_time_subframes (_transport_frame, time);
189 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
190 _mmc->send (MIDI::MachineControlCommand (time));
192 if (_transport_speed < 0.0f) {
193 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
195 todo = PostTransportWork (todo | PostTransportStop);
198 if (actively_recording()) {
200 /* move the transport position back to where the
201 request for a stop was noticed. we rolled
202 past that point to pick up delayed input (and/or to delick)
205 if (_worst_output_latency > current_block_size) {
206 /* we rolled past the stop point to pick up data that had
207 not yet arrived. move back to where the stop occured.
209 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
211 decrement_transport_position (current_block_size);
214 /* the duration change is not guaranteed to have happened, but is likely */
216 todo = PostTransportWork (todo | PostTransportDuration);
220 todo = PostTransportWork (todo | PostTransportAbort);
224 todo = PostTransportWork (todo | PostTransportClearSubstate);
228 add_post_transport_work (todo);
231 _clear_event_type (SessionEvent::StopOnce);
232 _clear_event_type (SessionEvent::RangeStop);
233 _clear_event_type (SessionEvent::RangeLocate);
235 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
236 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
238 reset_slave_state ();
240 _transport_speed = 0;
241 _target_transport_speed = 0;
243 g_atomic_int_set (&_playback_load, 100);
244 g_atomic_int_set (&_capture_load, 100);
246 if (config.get_use_video_sync()) {
247 waiting_for_sync_offset = true;
250 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
254 Session::butler_transport_work ()
258 PostTransportWork ptw;
259 boost::shared_ptr<RouteList> r = routes.reader ();
261 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
263 ptw = post_transport_work();
265 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
267 if (ptw & PostTransportAdjustPlaybackBuffering) {
268 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
269 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
271 tr->adjust_playback_buffering ();
272 /* and refill those buffers ... */
273 tr->non_realtime_locate (_transport_frame);
279 if (ptw & PostTransportAdjustCaptureBuffering) {
280 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
281 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
283 tr->adjust_capture_buffering ();
288 if (ptw & PostTransportCurveRealloc) {
289 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
290 (*i)->curve_reallocate();
294 if (ptw & PostTransportInputChange) {
295 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
296 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
298 tr->non_realtime_input_change ();
303 if (ptw & PostTransportSpeed) {
304 non_realtime_set_speed ();
307 if (ptw & PostTransportReverse) {
310 cumulative_rf_motion = 0;
313 /* don't seek if locate will take care of that in non_realtime_stop() */
315 if (!(ptw & PostTransportLocate)) {
317 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
318 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
319 if (tr && !tr->hidden()) {
320 tr->non_realtime_locate (_transport_frame);
322 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
323 /* new request, stop seeking, and start again */
324 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
331 if (ptw & PostTransportLocate) {
332 non_realtime_locate ();
335 if (ptw & PostTransportStop) {
336 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
338 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
343 if (ptw & PostTransportOverWrite) {
344 non_realtime_overwrite (on_entry, finished);
346 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
351 if (ptw & PostTransportAudition) {
352 non_realtime_set_audition ();
355 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
357 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
361 Session::non_realtime_set_speed ()
363 boost::shared_ptr<RouteList> rl = routes.reader();
364 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
365 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
367 tr->non_realtime_set_speed ();
373 Session::non_realtime_overwrite (int on_entry, bool& finished)
375 boost::shared_ptr<RouteList> rl = routes.reader();
376 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
377 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
378 if (tr && tr->pending_overwrite ()) {
379 tr->overwrite_existing_buffers ();
381 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
390 Session::non_realtime_locate ()
392 boost::shared_ptr<RouteList> rl = routes.reader();
393 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
394 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
396 tr->non_realtime_locate (_transport_frame);
403 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
409 PostTransportWork ptw = post_transport_work();
414 boost::shared_ptr<RouteList> rl = routes.reader();
415 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
416 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
417 if (tr && tr->get_captured_frames () != 0) {
423 /* stop and locate are merged here because they share a lot of common stuff */
426 now = localtime (&xnow);
429 auditioner->cancel_audition ();
433 cumulative_rf_motion = 0;
437 begin_reversible_command ("capture");
438 _have_captured = true;
441 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
442 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
443 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
445 tr->transport_stopped_wallclock (*now, xnow, abort);
449 boost::shared_ptr<RouteList> r = routes.reader ();
451 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
452 if (!(*i)->is_hidden()) {
453 (*i)->set_pending_declick (0);
458 commit_reversible_command ();
461 if (_engine.running()) {
462 update_latency_compensation (true, abort);
465 bool const auto_return_enabled =
466 (!config.get_external_sync() && config.get_auto_return());
468 if (auto_return_enabled ||
469 (ptw & PostTransportLocate) ||
470 (_requested_return_frame >= 0) ||
473 if (pending_locate_flush) {
474 flush_all_inserts ();
477 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
478 !(ptw & PostTransportLocate)) {
480 /* no explicit locate queued */
482 bool do_locate = false;
484 if (_requested_return_frame >= 0) {
486 /* explicit return request pre-queued in event list. overrides everything else */
488 cerr << "explicit auto-return to " << _requested_return_frame << endl;
490 _transport_frame = _requested_return_frame;
494 if (config.get_auto_return()) {
498 /* don't try to handle loop play when synced to JACK */
500 if (!synced_to_jack()) {
502 Location *location = _locations.auto_loop_location();
505 _transport_frame = location->start();
507 _transport_frame = _last_roll_location;
512 } else if (_play_range) {
514 /* return to start of range */
516 if (!current_audio_range.empty()) {
517 _transport_frame = current_audio_range.front().start;
523 /* regular auto-return */
525 _transport_frame = _last_roll_location;
531 _requested_return_frame = -1;
534 _engine.transport_locate (_transport_frame);
540 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
543 if (ptw & PostTransportClearSubstate) {
548 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
550 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
551 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
552 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
553 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
554 if (tr && !tr->hidden()) {
555 tr->non_realtime_locate (_transport_frame);
558 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
560 /* we will be back */
567 send_full_time_code (0);
569 if ((ptw & PostTransportLocate) && get_record_enabled()) {
570 /* capture start has been changed, so save pending state */
571 save_state ("", true);
575 /* always try to get rid of this */
577 remove_pending_capture_state ();
579 /* save the current state of things if appropriate */
581 if (did_record && !saved) {
582 save_state (_current_snapshot_name);
585 if (ptw & PostTransportStop) {
590 // can't cast away volatile so copy and emit that
591 nframes64_t tframe = _transport_frame;
592 PositionChanged (tframe); /* EMIT SIGNAL */
593 TransportStateChange (); /* EMIT SIGNAL */
595 /* and start it up again if relevant */
597 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
598 request_transport_speed (1.0);
599 pending_locate_roll = false;
604 Session::check_declick_out ()
606 bool locate_required = transport_sub_state & PendingLocate;
608 /* this is called after a process() iteration. if PendingDeclickOut was set,
609 it means that we were waiting to declick the output (which has just been
610 done) before doing something else. this is where we do that "something else".
612 note: called from the audio thread.
615 if (transport_sub_state & PendingDeclickOut) {
617 if (locate_required) {
618 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
619 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
621 stop_transport (pending_abort);
622 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
628 Session::unset_play_loop ()
631 clear_events (SessionEvent::AutoLoop);
633 // set all tracks to NOT use internal looping
634 boost::shared_ptr<RouteList> rl = routes.reader ();
635 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
636 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
637 if (tr && !tr->hidden()) {
644 Session::set_play_loop (bool yn)
646 /* Called from event-handling context */
650 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
651 /* nothing to do, or can't change loop status while recording */
657 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
658 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
659 "Recommend changing the configured options"), PROGRAM_NAME)
672 if (Config->get_seamless_loop()) {
673 // set all tracks to use internal looping
674 boost::shared_ptr<RouteList> rl = routes.reader ();
675 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
676 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
677 if (tr && !tr->hidden()) {
683 // set all tracks to NOT use internal looping
684 boost::shared_ptr<RouteList> rl = routes.reader ();
685 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
686 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
687 if (tr && !tr->hidden()) {
693 /* put the loop event into the event list */
695 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
698 /* locate to start of loop and roll. If doing seamless loop, force a
699 locate+buffer refill even if we are positioned there already.
702 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
710 TransportStateChange ();
713 Session::flush_all_inserts ()
715 boost::shared_ptr<RouteList> r = routes.reader ();
717 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
718 (*i)->flush_processors ();
723 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
725 if (synced_to_jack()) {
730 _slave->speed_and_position (sp, pos);
732 if (target_frame != pos) {
734 /* tell JACK to change transport position, and we will
735 follow along later in ::follow_slave()
738 _engine.transport_locate (target_frame);
740 if (sp != 1.0f && with_roll) {
741 _engine.transport_start ();
747 locate (target_frame, with_roll, with_flush, with_loop, force);
752 Session::micro_locate (nframes_t distance)
754 boost::shared_ptr<RouteList> rl = routes.reader();
755 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
756 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
757 if (tr && !tr->can_internal_playback_seek (distance)) {
762 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
763 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
765 tr->internal_playback_seek (distance);
769 _transport_frame += distance;
773 /** @param with_mmc true to send a MMC locate command when the locate is done */
775 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
777 if (actively_recording() && !with_loop) {
781 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
783 set_transport_speed (1.0, false);
785 loop_changing = false;
789 // Update Timecode time
790 // [DR] FIXME: find out exactly where this should go below
791 _transport_frame = target_frame;
792 timecode_time(_transport_frame, transmitting_timecode_time);
793 outbound_mtc_timecode_frame = _transport_frame;
794 next_quarter_frame_to_send = 0;
796 if (_transport_speed && (!with_loop || loop_changing)) {
797 /* schedule a declick. we'll be called again when its done */
799 if (!(transport_sub_state & PendingDeclickOut)) {
800 transport_sub_state |= (PendingDeclickOut|PendingLocate);
801 pending_locate_frame = target_frame;
802 pending_locate_roll = with_roll;
803 pending_locate_flush = with_flush;
808 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
809 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
812 if (force || !with_loop || loop_changing) {
814 PostTransportWork todo = PostTransportLocate;
817 todo = PostTransportWork (todo | PostTransportRoll);
820 add_post_transport_work (todo);
821 _butler->schedule_transport_work ();
825 /* this is functionally what clear_clicks() does but with a tentative lock */
827 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
829 if (clickm.locked()) {
831 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
840 /* switch from input if we're going to roll */
841 if (Config->get_monitoring_model() == HardwareMonitoring) {
843 boost::shared_ptr<RouteList> rl = routes.reader();
844 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
845 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
846 if (tr && tr->record_enabled ()) {
847 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
848 tr->monitor_input (!config.get_auto_input());
853 /* otherwise we're going to stop, so do the opposite */
854 if (Config->get_monitoring_model() == HardwareMonitoring) {
856 boost::shared_ptr<RouteList> rl = routes.reader();
857 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
858 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
859 if (tr && tr->record_enabled ()) {
860 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
861 tr->monitor_input (true);
867 /* cancel looped playback if transport pos outside of loop range */
869 Location* al = _locations.auto_loop_location();
871 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
872 // cancel looping directly, this is called from event handling context
873 set_play_loop (false);
875 else if (al && _transport_frame == al->start()) {
877 // this is only necessary for seamless looping
879 boost::shared_ptr<RouteList> rl = routes.reader();
880 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
881 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
882 if (tr && tr->record_enabled ()) {
883 // tell it we've looped, so it can deal with the record state
884 tr->transport_looped(_transport_frame);
889 TransportLooped(); // EMIT SIGNAL
893 loop_changing = false;
895 _send_timecode_update = true;
899 timecode_time_subframes (_transport_frame, time);
900 _mmc->send (MIDI::MachineControlCommand (time));
903 Located (); /* EMIT SIGNAL */
906 /** Set the transport speed.
907 * @param speed New speed
911 Session::set_transport_speed (double speed, bool abort, bool clear_state)
913 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));
915 if (_transport_speed == speed) {
919 _target_transport_speed = fabs(speed);
921 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
922 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
926 speed = min (8.0, speed);
927 } else if (speed < 0) {
928 speed = max (-8.0, speed);
931 if (transport_rolling() && speed == 0.0) {
933 /* we are rolling and we want to stop */
935 if (Config->get_monitoring_model() == HardwareMonitoring)
937 boost::shared_ptr<RouteList> rl = routes.reader();
938 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
939 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
940 if (tr && tr->record_enabled ()) {
941 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
942 tr->monitor_input (true);
947 if (synced_to_jack ()) {
949 /* do this here because our response to the slave won't
955 _engine.transport_stop ();
957 stop_transport (abort);
960 } else if (transport_stopped() && speed == 1.0) {
962 /* we are stopped and we want to start rolling at speed 1 */
964 if (Config->get_monitoring_model() == HardwareMonitoring) {
966 boost::shared_ptr<RouteList> rl = routes.reader();
967 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
968 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
969 if (config.get_auto_input() && tr && tr->record_enabled ()) {
970 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
971 tr->monitor_input (false);
976 if (synced_to_jack()) {
977 _engine.transport_start ();
984 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
985 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
991 if (actively_recording()) {
995 if (speed > 0.0 && _transport_frame == current_end_frame()) {
999 if (speed < 0.0 && _transport_frame == 0) {
1005 /* if we are reversing relative to the current speed, or relative to the speed
1006 before the last stop, then we have to do extra work.
1009 PostTransportWork todo = PostTransportWork (0);
1011 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1012 todo = PostTransportWork (todo | PostTransportReverse);
1013 _last_roll_or_reversal_location = _transport_frame;
1016 _last_transport_speed = _transport_speed;
1017 _transport_speed = speed;
1019 boost::shared_ptr<RouteList> rl = routes.reader();
1020 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1021 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1022 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1023 todo = PostTransportWork (todo | PostTransportSpeed);
1029 add_post_transport_work (todo);
1030 _butler->schedule_transport_work ();
1036 /** Stop the transport. */
1038 Session::stop_transport (bool abort, bool clear_state)
1040 if (_transport_speed == 0.0f) {
1044 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1046 boost::shared_ptr<RouteList> rl = routes.reader();
1047 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1048 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1050 tr->prepare_to_stop (_transport_frame);
1054 /* we need to capture the audio that has still not yet been received by the system
1055 at the time the stop is requested, so we have to roll past that time.
1057 we want to declick before stopping, so schedule the autostop for one
1058 block before the actual end. we'll declick in the subsequent block,
1059 and then we'll really be stopped.
1062 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1063 _transport_frame + _worst_output_latency - current_block_size,
1067 transport_sub_state |= StopPendingCapture;
1068 pending_abort = abort;
1073 if ((transport_sub_state & PendingDeclickOut) == 0) {
1075 if (!(transport_sub_state & StopPendingCapture)) {
1076 boost::shared_ptr<RouteList> rl = routes.reader();
1077 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1078 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1080 tr->prepare_to_stop (_transport_frame);
1085 transport_sub_state |= PendingDeclickOut;
1086 /* we'll be called again after the declick */
1087 pending_abort = abort;
1091 realtime_stop (abort, clear_state);
1092 _butler->schedule_transport_work ();
1096 Session::start_transport ()
1098 _last_roll_location = _transport_frame;
1099 _last_roll_or_reversal_location = _transport_frame;
1101 have_looped = false;
1103 /* if record status is Enabled, move it to Recording. if its
1104 already Recording, move it to Disabled.
1107 switch (record_status()) {
1109 if (!config.get_punch_in()) {
1116 disable_record (false);
1124 transport_sub_state |= PendingDeclickIn;
1126 _transport_speed = 1.0;
1127 _target_transport_speed = 1.0;
1129 boost::shared_ptr<RouteList> rl = routes.reader();
1130 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1131 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1133 tr->realtime_set_speed (tr->speed(), true);
1137 Timecode::Time time;
1138 timecode_time_subframes (_transport_frame, time);
1139 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1141 TransportStateChange (); /* EMIT SIGNAL */
1144 /** Do any transport work in the audio thread that needs to be done after the
1145 * transport thread is finished. Audio thread, realtime safe.
1148 Session::post_transport ()
1150 PostTransportWork ptw = post_transport_work ();
1152 if (ptw & PostTransportAudition) {
1153 if (auditioner && auditioner->auditioning()) {
1154 process_function = &Session::process_audition;
1156 process_function = &Session::process_with_events;
1160 if (ptw & PostTransportStop) {
1162 transport_sub_state = 0;
1165 if (ptw & PostTransportLocate) {
1167 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1171 transport_sub_state = 0;
1176 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1179 set_post_transport_work (PostTransportWork (0));
1183 Session::reset_rf_scale (nframes_t motion)
1185 cumulative_rf_motion += motion;
1187 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1189 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1191 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1203 Session::use_sync_source (Slave* new_slave)
1205 /* Runs in process() context */
1207 bool non_rt_required = false;
1209 /* XXX this deletion is problematic because we're in RT context */
1214 boost::shared_ptr<RouteList> rl = routes.reader();
1215 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1216 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1217 if (tr && !tr->hidden()) {
1218 if (tr->realtime_set_speed (tr->speed(), true)) {
1219 non_rt_required = true;
1221 tr->set_slaved (_slave != 0);
1225 if (non_rt_required) {
1226 add_post_transport_work (PostTransportSpeed);
1227 _butler->schedule_transport_work ();
1234 Session::drop_sync_source ()
1236 request_sync_source (0);
1240 Session::switch_to_sync_source (SyncSource src)
1244 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1248 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1254 new_slave = new MTC_Slave (*this, *_mtc_port);
1257 catch (failed_constructor& err) {
1262 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1268 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1272 if (_midi_clock_port) {
1274 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1277 catch (failed_constructor& err) {
1282 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1288 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1292 new_slave = new JACK_Slave (_engine.jack());
1300 request_sync_source (new_slave);
1304 Session::reverse_track_buffers ()
1306 add_post_transport_work (PostTransportReverse);
1307 _butler->schedule_transport_work ();
1311 Session::set_track_speed (Track* track, double speed)
1313 if (track->realtime_set_speed (speed, false)) {
1314 add_post_transport_work (PostTransportSpeed);
1315 _butler->schedule_transport_work ();
1321 Session::unset_play_range ()
1323 _play_range = false;
1324 _clear_event_type (SessionEvent::RangeStop);
1325 _clear_event_type (SessionEvent::RangeLocate);
1329 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1333 /* Called from event-processing context */
1335 unset_play_range ();
1337 if (range.empty()) {
1338 /* _play_range set to false in unset_play_range()
1340 if (!leave_rolling) {
1341 /* stop transport */
1342 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1350 /* cancel loop play */
1353 list<AudioRange>::size_type sz = range.size();
1357 list<AudioRange>::iterator i = range.begin();
1358 list<AudioRange>::iterator next;
1360 while (i != range.end()) {
1365 /* locating/stopping is subject to delays for declicking.
1368 nframes_t requested_frame = (*i).end;
1370 if (requested_frame > current_block_size) {
1371 requested_frame -= current_block_size;
1373 requested_frame = 0;
1376 if (next == range.end()) {
1377 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1379 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1387 } else if (sz == 1) {
1389 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1394 /* save range so we can do auto-return etc. */
1396 current_audio_range = range;
1398 /* now start rolling at the right place */
1400 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1403 TransportStateChange ();
1407 Session::request_bounded_roll (nframes_t start, nframes_t end)
1409 AudioRange ar (start, end, 0);
1410 list<AudioRange> lar;
1413 request_play_range (&lar, true);
1416 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1418 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1419 ev->target2_frame = start;
1424 Session::engine_halted ()
1428 /* there will be no more calls to process(), so
1429 we'd better clean up for ourselves, right now.
1431 but first, make sure the butler is out of
1435 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1436 set_post_transport_work (PostTransportWork (0));
1439 realtime_stop (false, true);
1440 non_realtime_stop (false, 0, ignored);
1441 transport_sub_state = 0;
1443 TransportStateChange (); /* EMIT SIGNAL */
1448 Session::xrun_recovery ()
1450 // can't cast away volatile so copy and emit that
1451 nframes64_t tframe = _transport_frame;
1452 Xrun (tframe); //EMIT SIGNAL
1454 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1456 /* it didn't actually halt, but we need
1457 to handle things in the same way.
1465 Session::route_processors_changed (RouteProcessorChange c)
1467 if (c.type == RouteProcessorChange::MeterPointChange) {
1471 update_latency_compensation (false, false);
1476 Session::update_latency_compensation (bool with_stop, bool abort)
1478 bool update_jack = false;
1479 PostTransportWork ptw;
1481 if (_state_of_the_state & Deletion) {
1485 _worst_track_latency = 0;
1486 ptw = post_transport_work();
1488 #undef DEBUG_LATENCY
1489 #ifdef DEBUG_LATENCY
1490 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1493 boost::shared_ptr<RouteList> r = routes.reader ();
1495 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1498 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1501 nframes_t old_latency = (*i)->output()->signal_latency ();
1502 nframes_t track_latency = (*i)->update_total_latency ();
1504 if (old_latency != track_latency) {
1505 (*i)->input()->update_port_total_latencies ();
1506 (*i)->output()->update_port_total_latencies ();
1510 if (!(*i)->is_hidden() && ((*i)->active())) {
1511 _worst_track_latency = max (_worst_track_latency, track_latency);
1516 _engine.update_total_latencies ();
1519 #ifdef DEBUG_LATENCY
1520 cerr << "\tworst was " << _worst_track_latency << endl;
1523 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1524 (*i)->set_latency_delay (_worst_track_latency);
1527 set_worst_io_latencies ();
1529 /* reflect any changes in latencies into capture offsets
1532 boost::shared_ptr<RouteList> rl = routes.reader();
1533 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1534 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1536 tr->set_capture_offset ();
1542 Session::allow_auto_play (bool yn)
1544 auto_play_legal = yn;
1548 Session::reset_jack_connection (jack_client_t* jack)
1552 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1553 js->reset_client (jack);
1558 Session::maybe_stop (nframes_t limit)
1560 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1561 if (synced_to_jack () && config.get_jack_time_master ()) {
1562 _engine.transport_stop ();
1563 } else if (!synced_to_jack ()) {