2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "pbd/error.h"
27 #include "pbd/enumwriter.h"
28 #include "pbd/pthread_utils.h"
29 #include "pbd/memento_command.h"
31 #include "midi++/mmc.h"
32 #include "midi++/port.h"
33 #include "midi++/manager.h"
35 #include "ardour/ardour.h"
36 #include "ardour/audioengine.h"
37 #include "ardour/auditioner.h"
38 #include "ardour/butler.h"
39 #include "ardour/debug.h"
40 #include "ardour/location.h"
41 #include "ardour/session.h"
42 #include "ardour/slave.h"
47 using namespace ARDOUR;
51 Session::add_post_transport_work (PostTransportWork ptw)
53 PostTransportWork oldval;
54 PostTransportWork newval;
58 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
59 newval = PostTransportWork (oldval | ptw);
60 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
66 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
70 Session::request_input_change_handling ()
72 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
73 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
79 Session::request_sync_source (Slave* new_slave)
81 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
84 seamless = Config->get_seamless_loop ();
86 if (dynamic_cast<JACK_Slave*>(new_slave)) {
87 /* JACK cannot support seamless looping at present */
88 Config->set_seamless_loop (false);
90 /* reset to whatever the value was before we last switched slaves */
91 Config->set_seamless_loop (_was_seamless);
94 /* save value of seamless from before the switch */
95 _was_seamless = seamless;
97 ev->slave = new_slave;
102 Session::request_transport_speed (double speed)
104 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
105 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
110 Session::request_track_speed (Track* tr, double speed)
112 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
118 Session::request_stop (bool abort, bool clear_state)
120 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
121 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
126 Session::request_locate (framepos_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 (framepos_t target_frame, bool with_roll)
136 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
137 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
142 Session::request_play_loop (bool yn, bool leave_rolling)
145 Location *location = _locations->auto_loop_location();
147 if (location == 0 && yn) {
148 error << _("Cannot loop - no loop range defined")
153 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
154 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
157 if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
158 // request an immediate locate to refresh the tracks
159 // after disabling looping
160 request_locate (_transport_frame-1, false);
165 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
167 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
169 ev->audio_range = *range;
171 ev->audio_range.clear ();
173 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
178 Session::realtime_stop (bool abort, bool clear_state)
180 DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
181 PostTransportWork todo = PostTransportWork (0);
183 /* assume that when we start, we'll be moving forwards */
185 if (_transport_speed < 0.0f) {
186 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
188 todo = PostTransportWork (todo | PostTransportStop);
191 if (actively_recording()) {
193 /* move the transport position back to where the
194 request for a stop was noticed. we rolled
195 past that point to pick up delayed input (and/or to delick)
198 if (_worst_output_latency > current_block_size) {
199 /* we rolled past the stop point to pick up data that had
200 not yet arrived. move back to where the stop occured.
202 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
204 decrement_transport_position (current_block_size);
207 /* the duration change is not guaranteed to have happened, but is likely */
209 todo = PostTransportWork (todo | PostTransportDuration);
213 todo = PostTransportWork (todo | PostTransportAbort);
217 todo = PostTransportWork (todo | PostTransportClearSubstate);
221 add_post_transport_work (todo);
224 _clear_event_type (SessionEvent::StopOnce);
225 _clear_event_type (SessionEvent::RangeStop);
226 _clear_event_type (SessionEvent::RangeLocate);
228 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
229 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
231 reset_slave_state ();
233 _transport_speed = 0;
234 _target_transport_speed = 0;
236 g_atomic_int_set (&_playback_load, 100);
237 g_atomic_int_set (&_capture_load, 100);
239 if (config.get_use_video_sync()) {
240 waiting_for_sync_offset = true;
243 transport_sub_state = 0;
247 Session::butler_transport_work ()
251 PostTransportWork ptw;
252 boost::shared_ptr<RouteList> r = routes.reader ();
254 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
256 ptw = post_transport_work();
258 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
260 if (ptw & PostTransportAdjustPlaybackBuffering) {
261 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
262 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
264 tr->adjust_playback_buffering ();
265 /* and refill those buffers ... */
266 tr->non_realtime_locate (_transport_frame);
272 if (ptw & PostTransportAdjustCaptureBuffering) {
273 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
274 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
276 tr->adjust_capture_buffering ();
281 if (ptw & PostTransportCurveRealloc) {
282 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
283 (*i)->curve_reallocate();
287 if (ptw & PostTransportInputChange) {
288 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
289 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
291 tr->non_realtime_input_change ();
296 if (ptw & PostTransportSpeed) {
297 non_realtime_set_speed ();
300 if (ptw & PostTransportReverse) {
303 cumulative_rf_motion = 0;
306 /* don't seek if locate will take care of that in non_realtime_stop() */
308 if (!(ptw & PostTransportLocate)) {
310 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
311 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
312 if (tr && !tr->hidden()) {
313 tr->non_realtime_locate (_transport_frame);
315 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
316 /* new request, stop seeking, and start again */
317 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
324 if (ptw & PostTransportLocate) {
325 non_realtime_locate ();
328 if (ptw & PostTransportStop) {
329 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
331 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
336 if (ptw & PostTransportOverWrite) {
337 non_realtime_overwrite (on_entry, finished);
339 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
344 if (ptw & PostTransportAudition) {
345 non_realtime_set_audition ();
348 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
350 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
354 Session::non_realtime_set_speed ()
356 boost::shared_ptr<RouteList> rl = routes.reader();
357 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
358 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
360 tr->non_realtime_set_speed ();
366 Session::non_realtime_overwrite (int on_entry, bool& finished)
368 boost::shared_ptr<RouteList> rl = routes.reader();
369 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
370 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
371 if (tr && tr->pending_overwrite ()) {
372 tr->overwrite_existing_buffers ();
374 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
383 Session::non_realtime_locate ()
385 boost::shared_ptr<RouteList> rl = routes.reader();
386 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
387 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
389 tr->non_realtime_locate (_transport_frame);
396 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
402 PostTransportWork ptw = post_transport_work();
407 boost::shared_ptr<RouteList> rl = routes.reader();
408 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
409 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
410 if (tr && tr->get_captured_frames () != 0) {
416 /* stop and locate are merged here because they share a lot of common stuff */
419 now = localtime (&xnow);
422 auditioner->cancel_audition ();
426 cumulative_rf_motion = 0;
430 begin_reversible_command ("capture");
431 _have_captured = true;
434 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
436 if (abort && did_record) {
437 /* no reason to save the session file when we remove sources
439 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
442 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
443 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
445 tr->transport_stopped_wallclock (*now, xnow, abort);
449 if (abort && did_record) {
450 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
453 boost::shared_ptr<RouteList> r = routes.reader ();
455 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
456 if (!(*i)->is_hidden()) {
457 (*i)->set_pending_declick (0);
462 commit_reversible_command ();
465 if (_engine.running()) {
466 update_latency_compensation (true, abort);
469 bool const auto_return_enabled =
470 (!config.get_external_sync() && config.get_auto_return());
472 if (auto_return_enabled ||
473 (ptw & PostTransportLocate) ||
474 (_requested_return_frame >= 0) ||
477 if (pending_locate_flush) {
478 flush_all_inserts ();
481 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
482 !(ptw & PostTransportLocate)) {
484 /* no explicit locate queued */
486 bool do_locate = false;
488 if (_requested_return_frame >= 0) {
490 /* explicit return request pre-queued in event list. overrides everything else */
492 cerr << "explicit auto-return to " << _requested_return_frame << endl;
494 _transport_frame = _requested_return_frame;
498 if (config.get_auto_return()) {
502 /* don't try to handle loop play when synced to JACK */
504 if (!synced_to_jack()) {
506 Location *location = _locations->auto_loop_location();
509 _transport_frame = location->start();
511 _transport_frame = _last_roll_location;
516 } else if (_play_range) {
518 /* return to start of range */
520 if (!current_audio_range.empty()) {
521 _transport_frame = current_audio_range.front().start;
527 /* regular auto-return */
529 _transport_frame = _last_roll_location;
535 _requested_return_frame = -1;
538 _engine.transport_locate (_transport_frame);
544 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
547 if (ptw & PostTransportClearSubstate) {
552 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
554 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
555 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
556 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
557 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
558 if (tr && !tr->hidden()) {
559 tr->non_realtime_locate (_transport_frame);
562 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
564 /* we will be back */
571 send_full_time_code (_transport_frame);
572 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
573 send_mmc_locate (_transport_frame);
575 if ((ptw & PostTransportLocate) && get_record_enabled()) {
576 /* capture start has been changed, so save pending state */
577 save_state ("", true);
581 /* always try to get rid of this */
583 remove_pending_capture_state ();
585 /* save the current state of things if appropriate */
587 if (did_record && !saved) {
588 save_state (_current_snapshot_name);
591 if (ptw & PostTransportStop) {
596 PositionChanged (_transport_frame); /* EMIT SIGNAL */
597 TransportStateChange (); /* EMIT SIGNAL */
599 /* and start it up again if relevant */
601 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
602 request_transport_speed (1.0);
603 pending_locate_roll = false;
608 Session::check_declick_out ()
610 bool locate_required = transport_sub_state & PendingLocate;
612 /* this is called after a process() iteration. if PendingDeclickOut was set,
613 it means that we were waiting to declick the output (which has just been
614 done) before doing something else. this is where we do that "something else".
616 note: called from the audio thread.
619 if (transport_sub_state & PendingDeclickOut) {
621 if (locate_required) {
622 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
623 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
625 stop_transport (pending_abort);
626 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
632 Session::unset_play_loop ()
635 clear_events (SessionEvent::AutoLoop);
637 // set all tracks to NOT use internal looping
638 boost::shared_ptr<RouteList> rl = routes.reader ();
639 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
640 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
641 if (tr && !tr->hidden()) {
648 Session::set_play_loop (bool yn)
650 /* Called from event-handling context */
654 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
655 /* nothing to do, or can't change loop status while recording */
659 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
660 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
661 "Recommend changing the configured options"), PROGRAM_NAME)
674 if (Config->get_seamless_loop()) {
675 // set all tracks to use internal looping
676 boost::shared_ptr<RouteList> rl = routes.reader ();
677 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
678 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
679 if (tr && !tr->hidden()) {
685 // set all tracks to NOT use internal looping
686 boost::shared_ptr<RouteList> rl = routes.reader ();
687 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
688 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
689 if (tr && !tr->hidden()) {
695 /* put the loop event into the event list */
697 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
700 /* locate to start of loop and roll. If doing seamless loop, force a
701 locate+buffer refill even if we are positioned there already.
704 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
712 TransportStateChange ();
715 Session::flush_all_inserts ()
717 boost::shared_ptr<RouteList> r = routes.reader ();
719 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
720 (*i)->flush_processors ();
725 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
727 if (synced_to_jack()) {
732 _slave->speed_and_position (sp, pos);
734 if (target_frame != pos) {
736 /* tell JACK to change transport position, and we will
737 follow along later in ::follow_slave()
740 _engine.transport_locate (target_frame);
742 if (sp != 1.0f && with_roll) {
743 _engine.transport_start ();
749 locate (target_frame, with_roll, with_flush, with_loop, force);
754 Session::micro_locate (nframes_t distance)
756 boost::shared_ptr<RouteList> rl = routes.reader();
757 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
758 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
759 if (tr && !tr->can_internal_playback_seek (distance)) {
764 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
765 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
767 tr->internal_playback_seek (distance);
771 _transport_frame += distance;
775 /** @param with_mmc true to send a MMC locate command when the locate is done */
777 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
779 if (actively_recording() && !with_loop) {
783 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
785 set_transport_speed (1.0, false);
787 loop_changing = false;
788 Located (); /* EMIT SIGNAL */
792 // Update Timecode time
793 // [DR] FIXME: find out exactly where this should go below
794 _transport_frame = target_frame;
795 timecode_time(_transport_frame, transmitting_timecode_time);
796 outbound_mtc_timecode_frame = _transport_frame;
797 next_quarter_frame_to_send = 0;
799 if (_transport_speed && (!with_loop || loop_changing)) {
800 /* schedule a declick. we'll be called again when its done */
802 if (!(transport_sub_state & PendingDeclickOut)) {
803 transport_sub_state |= (PendingDeclickOut|PendingLocate);
804 pending_locate_frame = target_frame;
805 pending_locate_roll = with_roll;
806 pending_locate_flush = with_flush;
811 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
812 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
815 if (force || !with_loop || loop_changing) {
817 PostTransportWork todo = PostTransportLocate;
820 todo = PostTransportWork (todo | PostTransportRoll);
823 add_post_transport_work (todo);
824 _butler->schedule_transport_work ();
828 /* this is functionally what clear_clicks() does but with a tentative lock */
830 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
832 if (clickm.locked()) {
834 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
843 /* switch from input if we're going to roll */
844 if (Config->get_monitoring_model() == HardwareMonitoring) {
846 boost::shared_ptr<RouteList> rl = routes.reader();
847 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
848 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
849 if (tr && tr->record_enabled ()) {
850 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
851 tr->monitor_input (!config.get_auto_input());
856 /* otherwise we're going to stop, so do the opposite */
857 if (Config->get_monitoring_model() == HardwareMonitoring) {
859 boost::shared_ptr<RouteList> rl = routes.reader();
860 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
861 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
862 if (tr && tr->record_enabled ()) {
863 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
864 tr->monitor_input (true);
870 /* cancel looped playback if transport pos outside of loop range */
872 Location* al = _locations->auto_loop_location();
874 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
875 // cancel looping directly, this is called from event handling context
876 set_play_loop (false);
878 else if (al && _transport_frame == al->start()) {
880 // this is only necessary for seamless looping
882 boost::shared_ptr<RouteList> rl = routes.reader();
883 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
884 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
885 if (tr && tr->record_enabled ()) {
886 // tell it we've looped, so it can deal with the record state
887 tr->transport_looped(_transport_frame);
892 TransportLooped(); // EMIT SIGNAL
896 loop_changing = false;
898 _send_timecode_update = true;
901 send_mmc_locate (_transport_frame);
904 Located (); /* EMIT SIGNAL */
907 /** Set the transport speed.
908 * @param speed New speed
912 Session::set_transport_speed (double speed, bool abort, bool clear_state)
914 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));
916 if (_transport_speed == speed) {
920 _target_transport_speed = fabs(speed);
922 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
923 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
927 speed = min (8.0, speed);
928 } else if (speed < 0) {
929 speed = max (-8.0, speed);
932 if (transport_rolling() && speed == 0.0) {
934 /* we are rolling and we want to stop */
936 if (Config->get_monitoring_model() == HardwareMonitoring)
938 boost::shared_ptr<RouteList> rl = routes.reader();
939 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
940 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
941 if (tr && tr->record_enabled ()) {
942 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
943 tr->monitor_input (true);
948 if (synced_to_jack ()) {
950 /* do this here because our response to the slave won't
956 _engine.transport_stop ();
958 stop_transport (abort);
961 } else if (transport_stopped() && speed == 1.0) {
963 /* we are stopped and we want to start rolling at speed 1 */
965 if (Config->get_monitoring_model() == HardwareMonitoring) {
967 boost::shared_ptr<RouteList> rl = routes.reader();
968 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
969 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
970 if (config.get_auto_input() && tr && tr->record_enabled ()) {
971 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
972 tr->monitor_input (false);
977 if (synced_to_jack()) {
978 _engine.transport_start ();
985 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
986 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
992 if (actively_recording()) {
996 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1000 if (speed < 0.0 && _transport_frame == 0) {
1006 /* if we are reversing relative to the current speed, or relative to the speed
1007 before the last stop, then we have to do extra work.
1010 PostTransportWork todo = PostTransportWork (0);
1012 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1013 todo = PostTransportWork (todo | PostTransportReverse);
1014 _last_roll_or_reversal_location = _transport_frame;
1017 _last_transport_speed = _transport_speed;
1018 _transport_speed = speed;
1020 boost::shared_ptr<RouteList> rl = routes.reader();
1021 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1022 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1023 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1024 todo = PostTransportWork (todo | PostTransportSpeed);
1030 add_post_transport_work (todo);
1031 _butler->schedule_transport_work ();
1037 /** Stop the transport. */
1039 Session::stop_transport (bool abort, bool clear_state)
1041 if (_transport_speed == 0.0f) {
1045 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1047 boost::shared_ptr<RouteList> rl = routes.reader();
1048 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1049 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1051 tr->prepare_to_stop (_transport_frame);
1055 /* we need to capture the audio that has still not yet been received by the system
1056 at the time the stop is requested, so we have to roll past that time.
1058 we want to declick before stopping, so schedule the autostop for one
1059 block before the actual end. we'll declick in the subsequent block,
1060 and then we'll really be stopped.
1063 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1064 _transport_frame + _worst_output_latency - current_block_size,
1068 transport_sub_state |= StopPendingCapture;
1069 pending_abort = abort;
1074 if ((transport_sub_state & PendingDeclickOut) == 0) {
1076 if (!(transport_sub_state & StopPendingCapture)) {
1077 boost::shared_ptr<RouteList> rl = routes.reader();
1078 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1079 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1081 tr->prepare_to_stop (_transport_frame);
1086 transport_sub_state |= PendingDeclickOut;
1087 /* we'll be called again after the declick */
1088 pending_abort = abort;
1092 realtime_stop (abort, clear_state);
1093 _butler->schedule_transport_work ();
1097 Session::start_transport ()
1099 _last_roll_location = _transport_frame;
1100 _last_roll_or_reversal_location = _transport_frame;
1102 have_looped = false;
1104 /* if record status is Enabled, move it to Recording. if its
1105 already Recording, move it to Disabled.
1108 switch (record_status()) {
1110 if (!config.get_punch_in()) {
1117 disable_record (false);
1125 transport_sub_state |= PendingDeclickIn;
1127 _transport_speed = 1.0;
1128 _target_transport_speed = 1.0;
1130 boost::shared_ptr<RouteList> rl = routes.reader();
1131 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1132 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1134 tr->realtime_set_speed (tr->speed(), true);
1136 (*i)->automation_snapshot (_transport_frame, true);
1139 Timecode::Time time;
1140 timecode_time_subframes (_transport_frame, time);
1141 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1143 TransportStateChange (); /* EMIT SIGNAL */
1146 /** Do any transport work in the audio thread that needs to be done after the
1147 * transport thread is finished. Audio thread, realtime safe.
1150 Session::post_transport ()
1152 PostTransportWork ptw = post_transport_work ();
1154 if (ptw & PostTransportAudition) {
1155 if (auditioner && auditioner->auditioning()) {
1156 process_function = &Session::process_audition;
1158 process_function = &Session::process_with_events;
1162 if (ptw & PostTransportStop) {
1164 transport_sub_state = 0;
1167 if (ptw & PostTransportLocate) {
1169 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1173 transport_sub_state = 0;
1178 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1181 set_post_transport_work (PostTransportWork (0));
1185 Session::reset_rf_scale (nframes_t motion)
1187 cumulative_rf_motion += motion;
1189 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1191 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1193 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1205 Session::use_sync_source (Slave* new_slave)
1207 /* Runs in process() context */
1209 bool non_rt_required = false;
1211 /* XXX this deletion is problematic because we're in RT context */
1216 boost::shared_ptr<RouteList> rl = routes.reader();
1217 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1218 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1219 if (tr && !tr->hidden()) {
1220 if (tr->realtime_set_speed (tr->speed(), true)) {
1221 non_rt_required = true;
1223 tr->set_slaved (_slave != 0);
1227 if (non_rt_required) {
1228 add_post_transport_work (PostTransportSpeed);
1229 _butler->schedule_transport_work ();
1236 Session::drop_sync_source ()
1238 request_sync_source (0);
1242 Session::switch_to_sync_source (SyncSource src)
1246 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1250 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1255 new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
1258 catch (failed_constructor& err) {
1264 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1269 new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
1272 catch (failed_constructor& err) {
1278 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1282 if (config.get_video_pullup() != 0.0f) {
1286 new_slave = new JACK_Slave (_engine.jack());
1294 request_sync_source (new_slave);
1298 Session::reverse_track_buffers ()
1300 add_post_transport_work (PostTransportReverse);
1301 _butler->schedule_transport_work ();
1305 Session::set_track_speed (Track* track, double speed)
1307 if (track->realtime_set_speed (speed, false)) {
1308 add_post_transport_work (PostTransportSpeed);
1309 _butler->schedule_transport_work ();
1315 Session::unset_play_range ()
1317 _play_range = false;
1318 _clear_event_type (SessionEvent::RangeStop);
1319 _clear_event_type (SessionEvent::RangeLocate);
1323 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1327 /* Called from event-processing context */
1329 unset_play_range ();
1331 if (range.empty()) {
1332 /* _play_range set to false in unset_play_range()
1334 if (!leave_rolling) {
1335 /* stop transport */
1336 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1344 /* cancel loop play */
1347 list<AudioRange>::size_type sz = range.size();
1351 list<AudioRange>::iterator i = range.begin();
1352 list<AudioRange>::iterator next;
1354 while (i != range.end()) {
1359 /* locating/stopping is subject to delays for declicking.
1362 nframes_t requested_frame = (*i).end;
1364 if (requested_frame > current_block_size) {
1365 requested_frame -= current_block_size;
1367 requested_frame = 0;
1370 if (next == range.end()) {
1371 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1373 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1381 } else if (sz == 1) {
1383 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1388 /* save range so we can do auto-return etc. */
1390 current_audio_range = range;
1392 /* now start rolling at the right place */
1394 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1397 TransportStateChange ();
1401 Session::request_bounded_roll (framepos_t start, framepos_t end)
1403 AudioRange ar (start, end, 0);
1404 list<AudioRange> lar;
1407 request_play_range (&lar, true);
1410 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1412 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1413 ev->target2_frame = start;
1418 Session::engine_halted ()
1422 /* there will be no more calls to process(), so
1423 we'd better clean up for ourselves, right now.
1425 but first, make sure the butler is out of
1429 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1430 set_post_transport_work (PostTransportWork (0));
1433 realtime_stop (false, true);
1434 non_realtime_stop (false, 0, ignored);
1435 transport_sub_state = 0;
1437 TransportStateChange (); /* EMIT SIGNAL */
1442 Session::xrun_recovery ()
1444 Xrun (_transport_frame); //EMIT SIGNAL
1446 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1448 /* it didn't actually halt, but we need
1449 to handle things in the same way.
1457 Session::route_processors_changed (RouteProcessorChange c)
1459 if (c.type == RouteProcessorChange::MeterPointChange) {
1463 update_latency_compensation (false, false);
1468 Session::update_latency_compensation (bool with_stop, bool abort)
1470 bool update_jack = false;
1471 PostTransportWork ptw;
1473 if (_state_of_the_state & Deletion) {
1477 _worst_track_latency = 0;
1478 ptw = post_transport_work();
1480 #undef DEBUG_LATENCY
1481 #ifdef DEBUG_LATENCY
1482 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1485 boost::shared_ptr<RouteList> r = routes.reader ();
1487 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1490 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1493 nframes_t old_latency = (*i)->output()->signal_latency ();
1494 nframes_t track_latency = (*i)->update_total_latency ();
1496 if (old_latency != track_latency) {
1497 (*i)->input()->update_port_total_latencies ();
1498 (*i)->output()->update_port_total_latencies ();
1502 if (!(*i)->is_hidden() && ((*i)->active())) {
1503 _worst_track_latency = max (_worst_track_latency, track_latency);
1508 _engine.update_total_latencies ();
1511 #ifdef DEBUG_LATENCY
1512 cerr << "\tworst was " << _worst_track_latency << endl;
1515 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1516 (*i)->set_latency_delay (_worst_track_latency);
1519 set_worst_io_latencies ();
1521 /* reflect any changes in latencies into capture offsets
1524 boost::shared_ptr<RouteList> rl = routes.reader();
1525 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1526 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1528 tr->set_capture_offset ();
1534 Session::allow_auto_play (bool yn)
1536 auto_play_legal = yn;
1540 Session::reset_jack_connection (jack_client_t* jack)
1544 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1545 js->reset_client (jack);
1550 Session::maybe_stop (nframes_t limit)
1552 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1553 if (synced_to_jack () && config.get_jack_time_master ()) {
1554 _engine.transport_stop ();
1555 } else if (!synced_to_jack ()) {
1564 Session::send_mmc_locate (framepos_t t)
1566 Timecode::Time time;
1567 timecode_time_subframes (t, time);
1568 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
1571 /** Ask the transport to not send timecode until further notice. The suspension
1572 * will come into effect some finite time after this call, and timecode_transmission_suspended()
1573 * should be checked by the caller to find out when.
1576 Session::request_suspend_timecode_transmission ()
1578 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1583 Session::request_resume_timecode_transmission ()
1585 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1590 Session::timecode_transmission_suspended () const
1592 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;