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.
24 #include <sigc++/bind.h>
25 #include <sigc++/retype.h>
28 #include "pbd/error.h"
29 #include "pbd/enumwriter.h"
30 #include "pbd/pthread_utils.h"
31 #include "pbd/memento_command.h"
33 #include "midi++/mmc.h"
34 #include "midi++/port.h"
36 #include "ardour/ardour.h"
37 #include "ardour/audio_diskstream.h"
38 #include "ardour/audioengine.h"
39 #include "ardour/auditioner.h"
40 #include "ardour/butler.h"
41 #include "ardour/debug.h"
42 #include "ardour/location.h"
43 #include "ardour/session.h"
44 #include "ardour/slave.h"
49 using namespace ARDOUR;
54 Session::add_post_transport_work (PostTransportWork ptw)
56 PostTransportWork oldval;
57 PostTransportWork newval;
61 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
62 newval = PostTransportWork (oldval | ptw);
63 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
69 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
73 Session::request_input_change_handling ()
75 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
76 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
82 Session::request_sync_source (Slave* new_slave)
84 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
87 seamless = Config->get_seamless_loop ();
89 if (dynamic_cast<JACK_Slave*>(new_slave)) {
90 /* JACK cannot support seamless looping at present */
91 Config->set_seamless_loop (false);
93 /* reset to whatever the value was before we last switched slaves */
94 Config->set_seamless_loop (_was_seamless);
97 /* save value of seamless from before the switch */
98 _was_seamless = seamless;
100 ev->slave = new_slave;
105 Session::request_transport_speed (double speed)
107 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
108 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
113 Session::request_diskstream_speed (Diskstream& ds, double speed)
115 SessionEvent* ev = new SessionEvent (SessionEvent::SetDiskstreamSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
121 Session::request_stop (bool abort, bool clear_state)
123 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
124 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
129 Session::request_locate (nframes_t target_frame, bool with_roll)
131 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
132 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
137 Session::force_locate (nframes64_t target_frame, bool with_roll)
139 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
140 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
145 Session::request_play_loop (bool yn, bool leave_rolling)
148 Location *location = _locations.auto_loop_location();
150 if (location == 0 && yn) {
151 error << _("Cannot loop - no loop range defined")
156 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
157 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
160 if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
161 // request an immediate locate to refresh the diskstreams
162 // after disabling looping
163 request_locate (_transport_frame-1, false);
168 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
170 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
172 ev->audio_range = *range;
174 ev->audio_range.clear ();
176 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
181 Session::realtime_stop (bool abort, bool clear_state)
183 DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
184 PostTransportWork todo = PostTransportWork (0);
186 /* assume that when we start, we'll be moving forwards */
188 // FIXME: where should this really be? [DR]
189 //send_full_time_code();
190 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
191 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
193 if (_transport_speed < 0.0f) {
194 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
196 todo = PostTransportWork (todo | PostTransportStop);
199 if (actively_recording()) {
201 /* move the transport position back to where the
202 request for a stop was noticed. we rolled
203 past that point to pick up delayed input.
206 decrement_transport_position (_worst_output_latency);
208 /* the duration change is not guaranteed to have happened, but is likely */
210 todo = PostTransportWork (todo | PostTransportDuration);
214 todo = PostTransportWork (todo | PostTransportAbort);
218 todo = PostTransportWork (todo | PostTransportClearSubstate);
222 add_post_transport_work (todo);
225 _clear_event_type (SessionEvent::StopOnce);
226 _clear_event_type (SessionEvent::RangeStop);
227 _clear_event_type (SessionEvent::RangeLocate);
229 disable_record (true);
231 reset_slave_state ();
233 _transport_speed = 0;
234 _target_transport_speed = 0;
236 if (config.get_use_video_sync()) {
237 waiting_for_sync_offset = true;
240 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
244 Session::butler_transport_work ()
248 PostTransportWork ptw;
249 boost::shared_ptr<RouteList> r = routes.reader ();
250 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
252 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
254 ptw = post_transport_work();
256 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
258 if (ptw & PostTransportCurveRealloc) {
259 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
260 (*i)->curve_reallocate();
264 if (ptw & PostTransportInputChange) {
265 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
266 (*i)->non_realtime_input_change ();
270 if (ptw & PostTransportSpeed) {
271 non_realtime_set_speed ();
274 if (ptw & PostTransportReverse) {
277 cumulative_rf_motion = 0;
280 /* don't seek if locate will take care of that in non_realtime_stop() */
282 if (!(ptw & PostTransportLocate)) {
284 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
285 if (!(*i)->hidden()) {
286 (*i)->non_realtime_locate (_transport_frame);
288 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
289 /* new request, stop seeking, and start again */
290 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
297 if (ptw & PostTransportLocate) {
298 non_realtime_locate ();
301 if (ptw & PostTransportStop) {
302 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
304 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
309 if (ptw & PostTransportOverWrite) {
310 non_realtime_overwrite (on_entry, finished);
312 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
317 if (ptw & PostTransportAudition) {
318 non_realtime_set_audition ();
321 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
325 Session::non_realtime_set_speed ()
327 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
329 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
330 (*i)->non_realtime_set_speed ();
335 Session::non_realtime_overwrite (int on_entry, bool& finished)
337 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
339 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
340 if ((*i)->pending_overwrite) {
341 (*i)->overwrite_existing_buffers ();
343 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
352 Session::non_realtime_locate ()
354 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
356 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
357 (*i)->non_realtime_locate (_transport_frame);
363 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
369 PostTransportWork ptw = post_transport_work();
374 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
376 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
377 if ((*i)->get_captured_frames () != 0) {
383 /* stop and locate are merged here because they share a lot of common stuff */
386 now = localtime (&xnow);
389 auditioner->cancel_audition ();
393 cumulative_rf_motion = 0;
397 begin_reversible_command ("capture");
399 Location* loc = _locations.end_location();
400 bool change_end = false;
402 if (_transport_frame < loc->end()) {
404 /* stopped recording before current end */
406 if (config.get_end_marker_is_free()) {
408 /* first capture for this session, move end back to where we are */
413 } else if (_transport_frame > loc->end()) {
415 /* stopped recording after the current end, extend it */
421 XMLNode &before = loc->get_state();
422 loc->set_end(_transport_frame);
423 XMLNode &after = loc->get_state();
424 add_command (new MementoCommand<Location>(*loc, &before, &after));
427 config.set_end_marker_is_free (false);
428 _have_captured = true;
431 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
432 (*i)->transport_stopped (*now, xnow, abort);
435 boost::shared_ptr<RouteList> r = routes.reader ();
437 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
438 if (!(*i)->is_hidden()) {
439 (*i)->set_pending_declick (0);
444 commit_reversible_command ();
447 if (_engine.running()) {
448 update_latency_compensation (true, abort);
451 bool const auto_return_enabled =
452 (!config.get_external_sync() && config.get_auto_return());
454 if (auto_return_enabled ||
455 (ptw & PostTransportLocate) ||
456 (_requested_return_frame >= 0) ||
459 if (pending_locate_flush) {
460 flush_all_inserts ();
463 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
464 !(ptw & PostTransportLocate)) {
466 /* no explicit locate queued */
468 bool do_locate = false;
470 if (_requested_return_frame >= 0) {
472 /* explicit return request pre-queued in event list. overrides everything else */
474 cerr << "explicit auto-return to " << _requested_return_frame << endl;
476 _transport_frame = _requested_return_frame;
480 if (config.get_auto_return()) {
484 /* don't try to handle loop play when synced to JACK */
486 if (!synced_to_jack()) {
488 Location *location = _locations.auto_loop_location();
491 _transport_frame = location->start();
493 _transport_frame = _last_roll_location;
498 } else if (_play_range) {
500 /* return to start of range */
502 if (!current_audio_range.empty()) {
503 _transport_frame = current_audio_range.front().start;
509 /* regular auto-return */
511 _transport_frame = _last_roll_location;
517 _requested_return_frame = -1;
520 _engine.transport_locate (_transport_frame);
526 /* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode.
529 if (ptw & PostTransportClearSubstate) {
534 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
537 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
538 if (!(*i)->hidden()) {
539 (*i)->non_realtime_locate (_transport_frame);
541 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
543 /* we will be back */
550 send_full_time_code (0);
551 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
552 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
554 if ((ptw & PostTransportLocate) && get_record_enabled()) {
555 /* capture start has been changed, so save pending state */
556 save_state ("", true);
560 /* always try to get rid of this */
562 remove_pending_capture_state ();
564 /* save the current state of things if appropriate */
566 if (did_record && !saved) {
567 save_state (_current_snapshot_name);
570 if (ptw & PostTransportDuration) {
571 DurationChanged (); /* EMIT SIGNAL */
574 if (ptw & PostTransportStop) {
579 PositionChanged ((nframes64_t) _transport_frame); /* EMIT SIGNAL */
580 TransportStateChange (); /* EMIT SIGNAL */
582 /* and start it up again if relevant */
584 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
585 request_transport_speed (1.0);
586 pending_locate_roll = false;
591 Session::check_declick_out ()
593 bool locate_required = transport_sub_state & PendingLocate;
595 /* this is called after a process() iteration. if PendingDeclickOut was set,
596 it means that we were waiting to declick the output (which has just been
597 done) before doing something else. this is where we do that "something else".
599 note: called from the audio thread.
602 if (transport_sub_state & PendingDeclickOut) {
604 if (locate_required) {
605 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
606 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
608 stop_transport (pending_abort);
609 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
615 Session::unset_play_loop ()
618 clear_events (SessionEvent::AutoLoop);
620 // set all diskstreams to NOT use internal looping
621 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
622 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
623 if (!(*i)->hidden()) {
630 Session::set_play_loop (bool yn)
632 /* Called from event-handling context */
636 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
637 /* nothing to do, or can't change loop status while recording */
643 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
644 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
645 "Recommend changing the configured options")
658 if (Config->get_seamless_loop()) {
659 // set all diskstreams to use internal looping
660 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
661 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
662 if (!(*i)->hidden()) {
663 (*i)->set_loop (loc);
668 // set all diskstreams to NOT use internal looping
669 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
670 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
671 if (!(*i)->hidden()) {
677 /* put the loop event into the event list */
679 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
682 /* locate to start of loop and roll. If doing seamless loop, force a
683 locate+buffer refill even if we are positioned there already.
686 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
694 TransportStateChange ();
697 Session::flush_all_inserts ()
699 boost::shared_ptr<RouteList> r = routes.reader ();
701 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
702 (*i)->flush_processors ();
707 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
709 if (synced_to_jack()) {
714 _slave->speed_and_position (sp, pos);
716 if (target_frame != pos) {
718 /* tell JACK to change transport position, and we will
719 follow along later in ::follow_slave()
722 _engine.transport_locate (target_frame);
724 if (sp != 1.0f && with_roll) {
725 _engine.transport_start ();
731 locate (target_frame, with_roll, with_flush, with_loop, force);
736 Session::micro_locate (nframes_t distance)
738 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
740 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
741 if (!(*i)->can_internal_playback_seek (distance)) {
746 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
747 (*i)->internal_playback_seek (distance);
750 _transport_frame += distance;
755 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
757 if (actively_recording() && !with_loop) {
761 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
763 set_transport_speed (1.0, false);
765 loop_changing = false;
769 // Update Timecode time
770 // [DR] FIXME: find out exactly where this should go below
771 _transport_frame = target_frame;
772 timecode_time(_transport_frame, transmitting_timecode_time);
773 outbound_mtc_timecode_frame = _transport_frame;
774 next_quarter_frame_to_send = 0;
776 if (_transport_speed && (!with_loop || loop_changing)) {
777 /* schedule a declick. we'll be called again when its done */
779 if (!(transport_sub_state & PendingDeclickOut)) {
780 transport_sub_state |= (PendingDeclickOut|PendingLocate);
781 pending_locate_frame = target_frame;
782 pending_locate_roll = with_roll;
783 pending_locate_flush = with_flush;
788 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
789 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
792 if (force || !with_loop || loop_changing) {
794 PostTransportWork todo = PostTransportLocate;
797 todo = PostTransportWork (todo | PostTransportRoll);
800 add_post_transport_work (todo);
801 _butler->schedule_transport_work ();
805 /* this is functionally what clear_clicks() does but with a tentative lock */
807 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
809 if (clickm.locked()) {
811 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
820 /* switch from input if we're going to roll */
821 if (Config->get_monitoring_model() == HardwareMonitoring) {
823 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
825 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
826 if ((*i)->record_enabled ()) {
827 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
828 (*i)->monitor_input (!config.get_auto_input());
833 /* otherwise we're going to stop, so do the opposite */
834 if (Config->get_monitoring_model() == HardwareMonitoring) {
835 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
837 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
838 if ((*i)->record_enabled ()) {
839 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
840 (*i)->monitor_input (true);
846 /* cancel looped playback if transport pos outside of loop range */
848 Location* al = _locations.auto_loop_location();
850 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
851 // cancel looping directly, this is called from event handling context
852 set_play_loop (false);
854 else if (al && _transport_frame == al->start()) {
856 // this is only necessary for seamless looping
858 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
860 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
861 if ((*i)->record_enabled ()) {
862 // tell it we've looped, so it can deal with the record state
863 (*i)->transport_looped(_transport_frame);
868 TransportLooped(); // EMIT SIGNAL
872 loop_changing = false;
874 _send_timecode_update = true;
876 Located (); /* EMIT SIGNAL */
879 /** Set the transport speed.
880 * @param speed New speed
884 Session::set_transport_speed (double speed, bool abort, bool clear_state)
886 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));
888 if (_transport_speed == speed) {
892 _target_transport_speed = fabs(speed);
894 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
895 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
899 speed = min (8.0, speed);
900 } else if (speed < 0) {
901 speed = max (-8.0, speed);
904 if (transport_rolling() && speed == 0.0) {
906 /* we are rolling and we want to stop */
908 if (Config->get_monitoring_model() == HardwareMonitoring)
910 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
912 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
913 if ((*i)->record_enabled ()) {
914 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
915 (*i)->monitor_input (true);
920 if (synced_to_jack ()) {
922 /* do this here because our response to the slave won't
928 _engine.transport_stop ();
930 stop_transport (abort);
933 } else if (transport_stopped() && speed == 1.0) {
935 /* we are stopped and we want to start rolling at speed 1 */
937 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
941 if (Config->get_monitoring_model() == HardwareMonitoring) {
943 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
945 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
946 if (config.get_auto_input() && (*i)->record_enabled ()) {
947 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
948 (*i)->monitor_input (false);
953 if (synced_to_jack()) {
954 _engine.transport_start ();
961 /* if not recording, don't roll forward past end if told to stop there */
963 if (!get_record_enabled() && (speed > 0.0 && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame())) {
967 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
968 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
973 if (actively_recording()) {
977 if (speed > 0.0 && _transport_frame == current_end_frame()) {
981 if (speed < 0.0 && _transport_frame == 0) {
987 /* if we are reversing relative to the current speed, or relative to the speed
988 before the last stop, then we have to do extra work.
991 PostTransportWork todo = PostTransportWork (0);
993 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
994 todo = PostTransportWork (todo | PostTransportReverse);
997 _last_transport_speed = _transport_speed;
998 _transport_speed = speed;
1000 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1001 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1002 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1003 todo = PostTransportWork (todo | PostTransportSpeed);
1009 add_post_transport_work (todo);
1010 _butler->schedule_transport_work ();
1016 /** Stop the transport. */
1018 Session::stop_transport (bool abort, bool clear_state)
1020 if (_transport_speed == 0.0f) {
1024 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
1025 _worst_output_latency > current_block_size)
1028 /* we need to capture the audio that has still not yet been received by the system
1029 at the time the stop is requested, so we have to roll past that time.
1031 we want to declick before stopping, so schedule the autostop for one
1032 block before the actual end. we'll declick in the subsequent block,
1033 and then we'll really be stopped.
1036 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1037 _transport_frame + _worst_output_latency - current_block_size,
1041 transport_sub_state |= StopPendingCapture;
1042 pending_abort = abort;
1047 if ((transport_sub_state & PendingDeclickOut) == 0) {
1048 transport_sub_state |= PendingDeclickOut;
1049 /* we'll be called again after the declick */
1050 pending_abort = abort;
1054 realtime_stop (abort, clear_state);
1055 _butler->schedule_transport_work ();
1059 Session::start_transport ()
1061 _last_roll_location = _transport_frame;
1062 have_looped = false;
1064 /* if record status is Enabled, move it to Recording. if its
1065 already Recording, move it to Disabled.
1068 switch (record_status()) {
1070 if (!config.get_punch_in()) {
1077 disable_record (false);
1085 transport_sub_state |= PendingDeclickIn;
1087 _transport_speed = 1.0;
1088 _target_transport_speed = 1.0;
1090 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1091 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1092 (*i)->realtime_set_speed ((*i)->speed(), true);
1095 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
1097 TransportStateChange (); /* EMIT SIGNAL */
1100 /** Do any transport work in the audio thread that needs to be done after the
1101 * transport thread is finished. Audio thread, realtime safe.
1104 Session::post_transport ()
1106 PostTransportWork ptw = post_transport_work ();
1108 if (ptw & PostTransportAudition) {
1109 if (auditioner && auditioner->active()) {
1110 process_function = &Session::process_audition;
1112 process_function = &Session::process_with_events;
1116 if (ptw & PostTransportStop) {
1118 transport_sub_state = 0;
1121 if (ptw & PostTransportLocate) {
1123 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1127 transport_sub_state = 0;
1132 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1135 set_post_transport_work (PostTransportWork (0));
1139 Session::reset_rf_scale (nframes_t motion)
1141 cumulative_rf_motion += motion;
1143 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1145 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1147 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1159 Session::use_sync_source (Slave* new_slave)
1161 /* Runs in process() context */
1163 bool non_rt_required = false;
1165 /* XXX this deletion is problematic because we're in RT context */
1170 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1171 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1172 if (!(*i)->hidden()) {
1173 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1174 non_rt_required = true;
1176 (*i)->set_slaved (_slave != 0);
1180 if (non_rt_required) {
1181 add_post_transport_work (PostTransportSpeed);
1182 _butler->schedule_transport_work ();
1189 Session::drop_sync_source ()
1191 request_sync_source (0);
1195 Session::switch_to_sync_source (SyncSource src)
1199 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1203 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1209 new_slave = new MTC_Slave (*this, *_mtc_port);
1212 catch (failed_constructor& err) {
1217 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1223 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1227 if (_midi_clock_port) {
1229 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1232 catch (failed_constructor& err) {
1237 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1243 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1247 new_slave = new JACK_Slave (_engine.jack());
1255 request_sync_source (new_slave);
1259 Session::reverse_diskstream_buffers ()
1261 add_post_transport_work (PostTransportReverse);
1262 _butler->schedule_transport_work ();
1266 Session::set_diskstream_speed (Diskstream* stream, double speed)
1268 if (stream->realtime_set_speed (speed, false)) {
1269 add_post_transport_work (PostTransportSpeed);
1270 _butler->schedule_transport_work ();
1276 Session::unset_play_range ()
1278 _play_range = false;
1279 _clear_event_type (SessionEvent::RangeStop);
1280 _clear_event_type (SessionEvent::RangeLocate);
1284 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1288 /* Called from event-processing context */
1290 unset_play_range ();
1292 if (range.empty()) {
1293 /* _play_range set to false in unset_play_range()
1295 if (!leave_rolling) {
1296 /* stop transport */
1297 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1305 /* cancel loop play */
1308 list<AudioRange>::size_type sz = range.size();
1312 list<AudioRange>::iterator i = range.begin();
1313 list<AudioRange>::iterator next;
1315 while (i != range.end()) {
1320 /* locating/stopping is subject to delays for declicking.
1323 nframes_t requested_frame = (*i).end;
1325 if (requested_frame > current_block_size) {
1326 requested_frame -= current_block_size;
1328 requested_frame = 0;
1331 if (next == range.end()) {
1332 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1334 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1342 } else if (sz == 1) {
1344 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1349 /* save range so we can do auto-return etc. */
1351 current_audio_range = range;
1353 /* now start rolling at the right place */
1355 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1358 TransportStateChange ();
1362 Session::request_bounded_roll (nframes_t start, nframes_t end)
1364 AudioRange ar (start, end, 0);
1365 list<AudioRange> lar;
1368 request_play_range (&lar, true);
1371 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1373 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1374 ev->target2_frame = start;
1379 Session::engine_halted ()
1383 /* there will be no more calls to process(), so
1384 we'd better clean up for ourselves, right now.
1386 but first, make sure the butler is out of
1390 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1391 set_post_transport_work (PostTransportWork (0));
1394 realtime_stop (false, true);
1395 non_realtime_stop (false, 0, ignored);
1396 transport_sub_state = 0;
1398 TransportStateChange (); /* EMIT SIGNAL */
1403 Session::xrun_recovery ()
1405 Xrun ((nframes64_t)_transport_frame); //EMIT SIGNAL
1407 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1409 /* it didn't actually halt, but we need
1410 to handle things in the same way.
1418 Session::route_processors_changed (RouteProcessorChange c)
1420 if (c.type == RouteProcessorChange::MeterPointChange) {
1424 update_latency_compensation (false, false);
1428 Session::update_latency_compensation (bool with_stop, bool abort)
1430 bool update_jack = false;
1431 PostTransportWork ptw;
1433 if (_state_of_the_state & Deletion) {
1437 _worst_track_latency = 0;
1438 ptw = post_transport_work();
1440 #undef DEBUG_LATENCY
1441 #ifdef DEBUG_LATENCY
1442 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1445 boost::shared_ptr<RouteList> r = routes.reader ();
1447 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1450 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1453 nframes_t old_latency = (*i)->output()->signal_latency ();
1454 nframes_t track_latency = (*i)->update_total_latency ();
1456 if (old_latency != track_latency) {
1457 (*i)->input()->update_port_total_latencies ();
1458 (*i)->output()->update_port_total_latencies ();
1462 if (!(*i)->is_hidden() && ((*i)->active())) {
1463 _worst_track_latency = max (_worst_track_latency, track_latency);
1468 _engine.update_total_latencies ();
1471 #ifdef DEBUG_LATENCY
1472 cerr << "\tworst was " << _worst_track_latency << endl;
1475 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1476 (*i)->set_latency_delay (_worst_track_latency);
1479 set_worst_io_latencies ();
1481 /* reflect any changes in latencies into capture offsets
1484 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1486 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1487 (*i)->set_capture_offset ();
1492 Session::allow_auto_play (bool yn)
1494 auto_play_legal = yn;
1498 Session::reset_jack_connection (jack_client_t* jack)
1502 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1503 js->reset_client (jack);
1508 Session::maybe_stop (nframes_t limit)
1510 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1511 if (synced_to_jack () && config.get_jack_time_master ()) {
1512 _engine.transport_stop ();
1513 } else if (!synced_to_jack ()) {