2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "pbd/error.h"
27 #include "pbd/enumwriter.h"
28 #include "pbd/pthread_utils.h"
29 #include "pbd/memento_command.h"
31 #include "midi++/mmc.h"
32 #include "midi++/port.h"
34 #include "ardour/ardour.h"
35 #include "ardour/audio_diskstream.h"
36 #include "ardour/audioengine.h"
37 #include "ardour/auditioner.h"
38 #include "ardour/butler.h"
39 #include "ardour/debug.h"
40 #include "ardour/location.h"
41 #include "ardour/session.h"
42 #include "ardour/slave.h"
47 using namespace ARDOUR;
51 Session::add_post_transport_work (PostTransportWork ptw)
53 PostTransportWork oldval;
54 PostTransportWork newval;
58 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
59 newval = PostTransportWork (oldval | ptw);
60 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
66 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
70 Session::request_input_change_handling ()
72 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
73 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
79 Session::request_sync_source (Slave* new_slave)
81 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
84 seamless = Config->get_seamless_loop ();
86 if (dynamic_cast<JACK_Slave*>(new_slave)) {
87 /* JACK cannot support seamless looping at present */
88 Config->set_seamless_loop (false);
90 /* reset to whatever the value was before we last switched slaves */
91 Config->set_seamless_loop (_was_seamless);
94 /* save value of seamless from before the switch */
95 _was_seamless = seamless;
97 ev->slave = new_slave;
102 Session::request_transport_speed (double speed)
104 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
105 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
110 Session::request_diskstream_speed (Diskstream& ds, double speed)
112 SessionEvent* ev = new SessionEvent (SessionEvent::SetDiskstreamSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
118 Session::request_stop (bool abort, bool clear_state)
120 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
121 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
126 Session::request_locate (nframes_t target_frame, bool with_roll)
128 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
129 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
134 Session::force_locate (nframes64_t target_frame, bool with_roll)
136 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
137 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
142 Session::request_play_loop (bool yn, bool leave_rolling)
145 Location *location = _locations.auto_loop_location();
147 if (location == 0 && yn) {
148 error << _("Cannot loop - no loop range defined")
153 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
154 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
157 if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
158 // request an immediate locate to refresh the diskstreams
159 // after disabling looping
160 request_locate (_transport_frame-1, false);
165 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
167 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
169 ev->audio_range = *range;
171 ev->audio_range.clear ();
173 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
178 Session::realtime_stop (bool abort, bool clear_state)
180 DEBUG_TRACE (DEBUG::Transport, "realtime stop\n");
181 PostTransportWork todo = PostTransportWork (0);
183 /* assume that when we start, we'll be moving forwards */
185 // FIXME: where should this really be? [DR]
186 //send_full_time_code();
187 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
188 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
190 if (_transport_speed < 0.0f) {
191 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
193 todo = PostTransportWork (todo | PostTransportStop);
196 if (actively_recording()) {
198 /* move the transport position back to where the
199 request for a stop was noticed. we rolled
200 past that point to pick up delayed input (and/or to delick)
203 if (_worst_output_latency > current_block_size) {
204 /* we rolled past the stop point to pick up data that had
205 not yet arrived. move back to where the stop occured.
207 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
209 decrement_transport_position (current_block_size);
212 /* the duration change is not guaranteed to have happened, but is likely */
214 todo = PostTransportWork (todo | PostTransportDuration);
218 todo = PostTransportWork (todo | PostTransportAbort);
222 todo = PostTransportWork (todo | PostTransportClearSubstate);
226 add_post_transport_work (todo);
229 _clear_event_type (SessionEvent::StopOnce);
230 _clear_event_type (SessionEvent::RangeStop);
231 _clear_event_type (SessionEvent::RangeLocate);
233 disable_record (true);
235 reset_slave_state ();
237 _transport_speed = 0;
238 _target_transport_speed = 0;
240 if (config.get_use_video_sync()) {
241 waiting_for_sync_offset = true;
244 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
248 Session::butler_transport_work ()
252 PostTransportWork ptw;
253 boost::shared_ptr<RouteList> r = routes.reader ();
254 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
256 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
258 ptw = post_transport_work();
260 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
262 if (ptw & PostTransportCurveRealloc) {
263 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
264 (*i)->curve_reallocate();
268 if (ptw & PostTransportInputChange) {
269 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
270 (*i)->non_realtime_input_change ();
274 if (ptw & PostTransportSpeed) {
275 non_realtime_set_speed ();
278 if (ptw & PostTransportReverse) {
281 cumulative_rf_motion = 0;
284 /* don't seek if locate will take care of that in non_realtime_stop() */
286 if (!(ptw & PostTransportLocate)) {
288 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
289 if (!(*i)->hidden()) {
290 (*i)->non_realtime_locate (_transport_frame);
292 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
293 /* new request, stop seeking, and start again */
294 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
301 if (ptw & PostTransportLocate) {
302 non_realtime_locate ();
305 if (ptw & PostTransportStop) {
306 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
308 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
313 if (ptw & PostTransportOverWrite) {
314 non_realtime_overwrite (on_entry, finished);
316 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
321 if (ptw & PostTransportAudition) {
322 non_realtime_set_audition ();
325 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
329 Session::non_realtime_set_speed ()
331 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
333 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
334 (*i)->non_realtime_set_speed ();
339 Session::non_realtime_overwrite (int on_entry, bool& finished)
341 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
343 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
344 if ((*i)->pending_overwrite) {
345 (*i)->overwrite_existing_buffers ();
347 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
356 Session::non_realtime_locate ()
358 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
360 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
361 (*i)->non_realtime_locate (_transport_frame);
367 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
373 PostTransportWork ptw = post_transport_work();
378 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
380 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
381 if ((*i)->get_captured_frames () != 0) {
387 /* stop and locate are merged here because they share a lot of common stuff */
390 now = localtime (&xnow);
393 auditioner->cancel_audition ();
397 cumulative_rf_motion = 0;
401 begin_reversible_command ("capture");
403 Location* loc = _locations.session_range_location();
404 bool change_end = false;
406 if (_transport_frame < loc->end()) {
408 /* stopped recording before current end */
410 if (config.get_end_marker_is_free()) {
412 /* first capture for this session, move end back to where we are */
417 } else if (_transport_frame > loc->end()) {
419 /* stopped recording after the current end, extend it */
425 XMLNode &before = loc->get_state();
426 loc->set_end(_transport_frame);
427 XMLNode &after = loc->get_state();
428 add_command (new MementoCommand<Location>(*loc, &before, &after));
431 config.set_end_marker_is_free (false);
432 _have_captured = true;
435 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
436 (*i)->transport_stopped (*now, xnow, abort);
439 boost::shared_ptr<RouteList> r = routes.reader ();
441 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
442 if (!(*i)->is_hidden()) {
443 (*i)->set_pending_declick (0);
448 commit_reversible_command ();
451 if (_engine.running()) {
452 update_latency_compensation (true, abort);
455 bool const auto_return_enabled =
456 (!config.get_external_sync() && config.get_auto_return());
458 if (auto_return_enabled ||
459 (ptw & PostTransportLocate) ||
460 (_requested_return_frame >= 0) ||
463 if (pending_locate_flush) {
464 flush_all_inserts ();
467 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
468 !(ptw & PostTransportLocate)) {
470 /* no explicit locate queued */
472 bool do_locate = false;
474 if (_requested_return_frame >= 0) {
476 /* explicit return request pre-queued in event list. overrides everything else */
478 cerr << "explicit auto-return to " << _requested_return_frame << endl;
480 _transport_frame = _requested_return_frame;
484 if (config.get_auto_return()) {
488 /* don't try to handle loop play when synced to JACK */
490 if (!synced_to_jack()) {
492 Location *location = _locations.auto_loop_location();
495 _transport_frame = location->start();
497 _transport_frame = _last_roll_location;
502 } else if (_play_range) {
504 /* return to start of range */
506 if (!current_audio_range.empty()) {
507 _transport_frame = current_audio_range.front().start;
513 /* regular auto-return */
515 _transport_frame = _last_roll_location;
521 _requested_return_frame = -1;
524 _engine.transport_locate (_transport_frame);
530 /* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode.
533 if (ptw & PostTransportClearSubstate) {
538 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
541 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
542 if (!(*i)->hidden()) {
543 (*i)->non_realtime_locate (_transport_frame);
545 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
547 /* we will be back */
554 send_full_time_code (0);
555 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
556 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
558 if ((ptw & PostTransportLocate) && get_record_enabled()) {
559 /* capture start has been changed, so save pending state */
560 save_state ("", true);
564 /* always try to get rid of this */
566 remove_pending_capture_state ();
568 /* save the current state of things if appropriate */
570 if (did_record && !saved) {
571 save_state (_current_snapshot_name);
574 if (ptw & PostTransportDuration) {
575 DurationChanged (); /* EMIT SIGNAL */
578 if (ptw & PostTransportStop) {
583 // can't cast away volatile so copy and emit that
584 nframes64_t tframe = _transport_frame;
585 PositionChanged (tframe); /* EMIT SIGNAL */
586 TransportStateChange (); /* EMIT SIGNAL */
588 /* and start it up again if relevant */
590 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
591 request_transport_speed (1.0);
592 pending_locate_roll = false;
597 Session::check_declick_out ()
599 bool locate_required = transport_sub_state & PendingLocate;
601 /* this is called after a process() iteration. if PendingDeclickOut was set,
602 it means that we were waiting to declick the output (which has just been
603 done) before doing something else. this is where we do that "something else".
605 note: called from the audio thread.
608 if (transport_sub_state & PendingDeclickOut) {
610 if (locate_required) {
611 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
612 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
614 stop_transport (pending_abort);
615 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
621 Session::unset_play_loop ()
624 clear_events (SessionEvent::AutoLoop);
626 // set all diskstreams to NOT use internal looping
627 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
628 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
629 if (!(*i)->hidden()) {
636 Session::set_play_loop (bool yn)
638 /* Called from event-handling context */
642 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
643 /* nothing to do, or can't change loop status while recording */
649 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
650 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
651 "Recommend changing the configured options"), PROGRAM_NAME)
664 if (Config->get_seamless_loop()) {
665 // set all diskstreams to use internal looping
666 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
667 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
668 if (!(*i)->hidden()) {
669 (*i)->set_loop (loc);
674 // set all diskstreams to NOT use internal looping
675 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
676 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
677 if (!(*i)->hidden()) {
683 /* put the loop event into the event list */
685 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
688 /* locate to start of loop and roll. If doing seamless loop, force a
689 locate+buffer refill even if we are positioned there already.
692 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
700 TransportStateChange ();
703 Session::flush_all_inserts ()
705 boost::shared_ptr<RouteList> r = routes.reader ();
707 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
708 (*i)->flush_processors ();
713 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
715 if (synced_to_jack()) {
720 _slave->speed_and_position (sp, pos);
722 if (target_frame != pos) {
724 /* tell JACK to change transport position, and we will
725 follow along later in ::follow_slave()
728 _engine.transport_locate (target_frame);
730 if (sp != 1.0f && with_roll) {
731 _engine.transport_start ();
737 locate (target_frame, with_roll, with_flush, with_loop, force);
742 Session::micro_locate (nframes_t distance)
744 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
746 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
747 if (!(*i)->can_internal_playback_seek (distance)) {
752 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
753 (*i)->internal_playback_seek (distance);
756 _transport_frame += distance;
761 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
763 if (actively_recording() && !with_loop) {
767 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
769 set_transport_speed (1.0, false);
771 loop_changing = false;
775 // Update Timecode time
776 // [DR] FIXME: find out exactly where this should go below
777 _transport_frame = target_frame;
778 timecode_time(_transport_frame, transmitting_timecode_time);
779 outbound_mtc_timecode_frame = _transport_frame;
780 next_quarter_frame_to_send = 0;
782 if (_transport_speed && (!with_loop || loop_changing)) {
783 /* schedule a declick. we'll be called again when its done */
785 if (!(transport_sub_state & PendingDeclickOut)) {
786 transport_sub_state |= (PendingDeclickOut|PendingLocate);
787 pending_locate_frame = target_frame;
788 pending_locate_roll = with_roll;
789 pending_locate_flush = with_flush;
794 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
795 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
798 if (force || !with_loop || loop_changing) {
800 PostTransportWork todo = PostTransportLocate;
803 todo = PostTransportWork (todo | PostTransportRoll);
806 add_post_transport_work (todo);
807 _butler->schedule_transport_work ();
811 /* this is functionally what clear_clicks() does but with a tentative lock */
813 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
815 if (clickm.locked()) {
817 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
826 /* switch from input if we're going to roll */
827 if (Config->get_monitoring_model() == HardwareMonitoring) {
829 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
831 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
832 if ((*i)->record_enabled ()) {
833 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
834 (*i)->monitor_input (!config.get_auto_input());
839 /* otherwise we're going to stop, so do the opposite */
840 if (Config->get_monitoring_model() == HardwareMonitoring) {
841 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
843 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
844 if ((*i)->record_enabled ()) {
845 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
846 (*i)->monitor_input (true);
852 /* cancel looped playback if transport pos outside of loop range */
854 Location* al = _locations.auto_loop_location();
856 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
857 // cancel looping directly, this is called from event handling context
858 set_play_loop (false);
860 else if (al && _transport_frame == al->start()) {
862 // this is only necessary for seamless looping
864 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
866 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
867 if ((*i)->record_enabled ()) {
868 // tell it we've looped, so it can deal with the record state
869 (*i)->transport_looped(_transport_frame);
874 TransportLooped(); // EMIT SIGNAL
878 loop_changing = false;
880 _send_timecode_update = true;
882 Located (); /* EMIT SIGNAL */
885 /** Set the transport speed.
886 * @param speed New speed
890 Session::set_transport_speed (double speed, bool abort, bool clear_state)
892 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));
894 if (_transport_speed == speed) {
898 _target_transport_speed = fabs(speed);
900 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
901 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
905 speed = min (8.0, speed);
906 } else if (speed < 0) {
907 speed = max (-8.0, speed);
910 if (transport_rolling() && speed == 0.0) {
912 /* we are rolling and we want to stop */
914 if (Config->get_monitoring_model() == HardwareMonitoring)
916 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
918 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
919 if ((*i)->record_enabled ()) {
920 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
921 (*i)->monitor_input (true);
926 if (synced_to_jack ()) {
928 /* do this here because our response to the slave won't
934 _engine.transport_stop ();
936 stop_transport (abort);
939 } else if (transport_stopped() && speed == 1.0) {
941 /* we are stopped and we want to start rolling at speed 1 */
943 if (Config->get_monitoring_model() == HardwareMonitoring) {
945 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
947 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
948 if (config.get_auto_input() && (*i)->record_enabled ()) {
949 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
950 (*i)->monitor_input (false);
955 if (synced_to_jack()) {
956 _engine.transport_start ();
963 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
964 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
970 if (actively_recording()) {
974 if (speed > 0.0 && _transport_frame == current_end_frame()) {
978 if (speed < 0.0 && _transport_frame == 0) {
984 /* if we are reversing relative to the current speed, or relative to the speed
985 before the last stop, then we have to do extra work.
988 PostTransportWork todo = PostTransportWork (0);
990 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
991 todo = PostTransportWork (todo | PostTransportReverse);
994 _last_transport_speed = _transport_speed;
995 _transport_speed = speed;
997 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
998 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
999 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1000 todo = PostTransportWork (todo | PostTransportSpeed);
1006 add_post_transport_work (todo);
1007 _butler->schedule_transport_work ();
1013 /** Stop the transport. */
1015 Session::stop_transport (bool abort, bool clear_state)
1017 if (_transport_speed == 0.0f) {
1021 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1023 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1025 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1026 (*i)->prepare_to_stop (_transport_frame);
1029 /* we need to capture the audio that has still not yet been received by the system
1030 at the time the stop is requested, so we have to roll past that time.
1032 we want to declick before stopping, so schedule the autostop for one
1033 block before the actual end. we'll declick in the subsequent block,
1034 and then we'll really be stopped.
1037 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1038 _transport_frame + _worst_output_latency - current_block_size,
1042 transport_sub_state |= StopPendingCapture;
1043 pending_abort = abort;
1048 if ((transport_sub_state & PendingDeclickOut) == 0) {
1050 if (!(transport_sub_state & StopPendingCapture)) {
1051 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1053 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1054 (*i)->prepare_to_stop (_transport_frame);
1058 transport_sub_state |= PendingDeclickOut;
1059 /* we'll be called again after the declick */
1060 pending_abort = abort;
1064 realtime_stop (abort, clear_state);
1065 _butler->schedule_transport_work ();
1069 Session::start_transport ()
1071 _last_roll_location = _transport_frame;
1072 have_looped = false;
1074 /* if record status is Enabled, move it to Recording. if its
1075 already Recording, move it to Disabled.
1078 switch (record_status()) {
1080 if (!config.get_punch_in()) {
1087 disable_record (false);
1095 transport_sub_state |= PendingDeclickIn;
1097 _transport_speed = 1.0;
1098 _target_transport_speed = 1.0;
1100 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1101 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1102 (*i)->realtime_set_speed ((*i)->speed(), true);
1105 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
1107 TransportStateChange (); /* EMIT SIGNAL */
1110 /** Do any transport work in the audio thread that needs to be done after the
1111 * transport thread is finished. Audio thread, realtime safe.
1114 Session::post_transport ()
1116 PostTransportWork ptw = post_transport_work ();
1118 if (ptw & PostTransportAudition) {
1119 if (auditioner && auditioner->auditioning()) {
1120 process_function = &Session::process_audition;
1122 process_function = &Session::process_with_events;
1126 if (ptw & PostTransportStop) {
1128 transport_sub_state = 0;
1131 if (ptw & PostTransportLocate) {
1133 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1137 transport_sub_state = 0;
1142 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1145 set_post_transport_work (PostTransportWork (0));
1149 Session::reset_rf_scale (nframes_t motion)
1151 cumulative_rf_motion += motion;
1153 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1155 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1157 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1169 Session::use_sync_source (Slave* new_slave)
1171 /* Runs in process() context */
1173 bool non_rt_required = false;
1175 /* XXX this deletion is problematic because we're in RT context */
1180 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1181 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1182 if (!(*i)->hidden()) {
1183 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1184 non_rt_required = true;
1186 (*i)->set_slaved (_slave != 0);
1190 if (non_rt_required) {
1191 add_post_transport_work (PostTransportSpeed);
1192 _butler->schedule_transport_work ();
1199 Session::drop_sync_source ()
1201 request_sync_source (0);
1205 Session::switch_to_sync_source (SyncSource src)
1209 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1213 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1219 new_slave = new MTC_Slave (*this, *_mtc_port);
1222 catch (failed_constructor& err) {
1227 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1233 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1237 if (_midi_clock_port) {
1239 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1242 catch (failed_constructor& err) {
1247 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1253 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1257 new_slave = new JACK_Slave (_engine.jack());
1265 request_sync_source (new_slave);
1269 Session::reverse_diskstream_buffers ()
1271 add_post_transport_work (PostTransportReverse);
1272 _butler->schedule_transport_work ();
1276 Session::set_diskstream_speed (Diskstream* stream, double speed)
1278 if (stream->realtime_set_speed (speed, false)) {
1279 add_post_transport_work (PostTransportSpeed);
1280 _butler->schedule_transport_work ();
1286 Session::unset_play_range ()
1288 _play_range = false;
1289 _clear_event_type (SessionEvent::RangeStop);
1290 _clear_event_type (SessionEvent::RangeLocate);
1294 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1298 /* Called from event-processing context */
1300 unset_play_range ();
1302 if (range.empty()) {
1303 /* _play_range set to false in unset_play_range()
1305 if (!leave_rolling) {
1306 /* stop transport */
1307 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1315 /* cancel loop play */
1318 list<AudioRange>::size_type sz = range.size();
1322 list<AudioRange>::iterator i = range.begin();
1323 list<AudioRange>::iterator next;
1325 while (i != range.end()) {
1330 /* locating/stopping is subject to delays for declicking.
1333 nframes_t requested_frame = (*i).end;
1335 if (requested_frame > current_block_size) {
1336 requested_frame -= current_block_size;
1338 requested_frame = 0;
1341 if (next == range.end()) {
1342 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1344 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1352 } else if (sz == 1) {
1354 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1359 /* save range so we can do auto-return etc. */
1361 current_audio_range = range;
1363 /* now start rolling at the right place */
1365 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1368 TransportStateChange ();
1372 Session::request_bounded_roll (nframes_t start, nframes_t end)
1374 AudioRange ar (start, end, 0);
1375 list<AudioRange> lar;
1378 request_play_range (&lar, true);
1381 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1383 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1384 ev->target2_frame = start;
1389 Session::engine_halted ()
1393 /* there will be no more calls to process(), so
1394 we'd better clean up for ourselves, right now.
1396 but first, make sure the butler is out of
1400 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1401 set_post_transport_work (PostTransportWork (0));
1404 realtime_stop (false, true);
1405 non_realtime_stop (false, 0, ignored);
1406 transport_sub_state = 0;
1408 TransportStateChange (); /* EMIT SIGNAL */
1413 Session::xrun_recovery ()
1415 // can't cast away volatile so copy and emit that
1416 nframes64_t tframe = _transport_frame;
1417 Xrun (tframe); //EMIT SIGNAL
1419 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1421 /* it didn't actually halt, but we need
1422 to handle things in the same way.
1430 Session::route_processors_changed (RouteProcessorChange c)
1432 if (c.type == RouteProcessorChange::MeterPointChange) {
1436 update_latency_compensation (false, false);
1441 Session::update_latency_compensation (bool with_stop, bool abort)
1443 bool update_jack = false;
1444 PostTransportWork ptw;
1446 if (_state_of_the_state & Deletion) {
1450 _worst_track_latency = 0;
1451 ptw = post_transport_work();
1453 #undef DEBUG_LATENCY
1454 #ifdef DEBUG_LATENCY
1455 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1458 boost::shared_ptr<RouteList> r = routes.reader ();
1460 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1463 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1466 nframes_t old_latency = (*i)->output()->signal_latency ();
1467 nframes_t track_latency = (*i)->update_total_latency ();
1469 if (old_latency != track_latency) {
1470 (*i)->input()->update_port_total_latencies ();
1471 (*i)->output()->update_port_total_latencies ();
1475 if (!(*i)->is_hidden() && ((*i)->active())) {
1476 _worst_track_latency = max (_worst_track_latency, track_latency);
1481 _engine.update_total_latencies ();
1484 #ifdef DEBUG_LATENCY
1485 cerr << "\tworst was " << _worst_track_latency << endl;
1488 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1489 (*i)->set_latency_delay (_worst_track_latency);
1492 set_worst_io_latencies ();
1494 /* reflect any changes in latencies into capture offsets
1497 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1499 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1500 (*i)->set_capture_offset ();
1505 Session::allow_auto_play (bool yn)
1507 auto_play_legal = yn;
1511 Session::reset_jack_connection (jack_client_t* jack)
1515 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1516 js->reset_client (jack);
1521 Session::maybe_stop (nframes_t limit)
1523 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1524 if (synced_to_jack () && config.get_jack_time_master ()) {
1525 _engine.transport_stop ();
1526 } else if (!synced_to_jack ()) {