commits 6001-6525 inclusive from 2.X applied to 3.0
[ardour2.git] / libs / ardour / session_transport.cc
blobc5e6795325e41fbb61197169bf5b8a7bea1ca7d0
1 /*
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.
20 #include <cmath>
21 #include <cerrno>
22 #include <unistd.h>
25 #include "pbd/undo.h"
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"
44 #include "i18n.h"
46 using namespace std;
47 using namespace ARDOUR;
48 using namespace PBD;
50 void
51 Session::add_post_transport_work (PostTransportWork ptw)
53 PostTransportWork oldval;
54 PostTransportWork newval;
55 int tries = 0;
57 while (tries < 8) {
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)) {
61 /* success */
62 return;
66 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
69 void
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);
74 queue_event (ev);
78 void
79 Session::request_sync_source (Slave* new_slave)
81 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
82 bool seamless;
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);
89 } else {
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;
98 queue_event (ev);
101 void
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));
106 queue_event (ev);
109 void
110 Session::request_diskstream_speed (Diskstream& ds, double speed)
112 SessionEvent* ev = new SessionEvent (SessionEvent::SetDiskstreamSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
113 ev->set_ptr (&ds);
114 queue_event (ev);
117 void
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));
122 queue_event (ev);
125 void
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));
130 queue_event (ev);
133 void
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));
138 queue_event (ev);
141 void
142 Session::request_play_loop (bool yn, bool leave_rolling)
144 SessionEvent* ev;
145 Location *location = _locations.auto_loop_location();
147 if (location == 0 && yn) {
148 error << _("Cannot loop - no loop range defined")
149 << endmsg;
150 return;
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));
155 queue_event (ev);
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);
164 void
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));
168 if (range) {
169 ev->audio_range = *range;
170 } else {
171 ev->audio_range.clear ();
173 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
174 queue_event (ev);
177 void
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));
192 } else {
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));
208 } else {
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);
217 if (abort) {
218 todo = PostTransportWork (todo | PostTransportAbort);
221 if (clear_state) {
222 todo = PostTransportWork (todo | PostTransportClearSubstate);
225 if (todo) {
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 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
234 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
236 reset_slave_state ();
238 _transport_speed = 0;
239 _target_transport_speed = 0;
241 if (config.get_use_video_sync()) {
242 waiting_for_sync_offset = true;
245 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
248 void
249 Session::butler_transport_work ()
251 restart:
252 bool finished;
253 PostTransportWork ptw;
254 boost::shared_ptr<RouteList> r = routes.reader ();
255 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
257 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
258 finished = true;
259 ptw = post_transport_work();
261 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
263 if (ptw & PostTransportCurveRealloc) {
264 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
265 (*i)->curve_reallocate();
269 if (ptw & PostTransportInputChange) {
270 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
271 (*i)->non_realtime_input_change ();
275 if (ptw & PostTransportSpeed) {
276 non_realtime_set_speed ();
279 if (ptw & PostTransportReverse) {
281 clear_clicks();
282 cumulative_rf_motion = 0;
283 reset_rf_scale (0);
285 /* don't seek if locate will take care of that in non_realtime_stop() */
287 if (!(ptw & PostTransportLocate)) {
289 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
290 if (!(*i)->hidden()) {
291 (*i)->non_realtime_locate (_transport_frame);
293 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
294 /* new request, stop seeking, and start again */
295 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
296 goto restart;
302 if (ptw & PostTransportLocate) {
303 non_realtime_locate ();
306 if (ptw & PostTransportStop) {
307 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
308 if (!finished) {
309 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
310 goto restart;
314 if (ptw & PostTransportOverWrite) {
315 non_realtime_overwrite (on_entry, finished);
316 if (!finished) {
317 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
318 goto restart;
322 if (ptw & PostTransportAudition) {
323 non_realtime_set_audition ();
326 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
328 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
331 void
332 Session::non_realtime_set_speed ()
334 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
336 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
337 (*i)->non_realtime_set_speed ();
341 void
342 Session::non_realtime_overwrite (int on_entry, bool& finished)
344 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
346 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
347 if ((*i)->pending_overwrite) {
348 (*i)->overwrite_existing_buffers ();
350 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
351 finished = false;
352 return;
358 void
359 Session::non_realtime_locate ()
361 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
363 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
364 (*i)->non_realtime_locate (_transport_frame);
369 void
370 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
372 struct tm* now;
373 time_t xnow;
374 bool did_record;
375 bool saved;
376 PostTransportWork ptw = post_transport_work();
378 did_record = false;
379 saved = false;
381 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
383 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
384 if ((*i)->get_captured_frames () != 0) {
385 did_record = true;
386 break;
390 /* stop and locate are merged here because they share a lot of common stuff */
392 time (&xnow);
393 now = localtime (&xnow);
395 if (auditioner) {
396 auditioner->cancel_audition ();
399 clear_clicks();
400 cumulative_rf_motion = 0;
401 reset_rf_scale (0);
403 if (did_record) {
404 begin_reversible_command ("capture");
406 Location* loc = _locations.session_range_location();
407 bool change_end = false;
409 if (_transport_frame < loc->end()) {
411 /* stopped recording before current end */
413 if (config.get_end_marker_is_free()) {
415 /* first capture for this session, move end back to where we are */
417 change_end = true;
420 } else if (_transport_frame > loc->end()) {
422 /* stopped recording after the current end, extend it */
424 change_end = true;
427 if (change_end) {
428 XMLNode &before = loc->get_state();
429 loc->set_end(_transport_frame);
430 XMLNode &after = loc->get_state();
431 add_command (new MementoCommand<Location>(*loc, &before, &after));
434 config.set_end_marker_is_free (false);
435 _have_captured = true;
438 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
439 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
440 (*i)->transport_stopped (*now, xnow, abort);
443 boost::shared_ptr<RouteList> r = routes.reader ();
445 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
446 if (!(*i)->is_hidden()) {
447 (*i)->set_pending_declick (0);
451 if (did_record) {
452 commit_reversible_command ();
455 if (_engine.running()) {
456 update_latency_compensation (true, abort);
459 bool const auto_return_enabled =
460 (!config.get_external_sync() && config.get_auto_return());
462 if (auto_return_enabled ||
463 (ptw & PostTransportLocate) ||
464 (_requested_return_frame >= 0) ||
465 synced_to_jack()) {
467 if (pending_locate_flush) {
468 flush_all_inserts ();
471 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
472 !(ptw & PostTransportLocate)) {
474 /* no explicit locate queued */
476 bool do_locate = false;
478 if (_requested_return_frame >= 0) {
480 /* explicit return request pre-queued in event list. overrides everything else */
482 cerr << "explicit auto-return to " << _requested_return_frame << endl;
484 _transport_frame = _requested_return_frame;
485 do_locate = true;
487 } else {
488 if (config.get_auto_return()) {
490 if (play_loop) {
492 /* don't try to handle loop play when synced to JACK */
494 if (!synced_to_jack()) {
496 Location *location = _locations.auto_loop_location();
498 if (location != 0) {
499 _transport_frame = location->start();
500 } else {
501 _transport_frame = _last_roll_location;
503 do_locate = true;
506 } else if (_play_range) {
508 /* return to start of range */
510 if (!current_audio_range.empty()) {
511 _transport_frame = current_audio_range.front().start;
512 do_locate = true;
515 } else {
517 /* regular auto-return */
519 _transport_frame = _last_roll_location;
520 do_locate = true;
525 _requested_return_frame = -1;
527 if (do_locate) {
528 _engine.transport_locate (_transport_frame);
534 /* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode.
537 if (ptw & PostTransportClearSubstate) {
538 _play_range = false;
539 unset_play_loop ();
542 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
545 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
547 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
548 if (!(*i)->hidden()) {
549 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
550 (*i)->non_realtime_locate (_transport_frame);
553 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
554 finished = false;
555 /* we will be back */
556 return;
560 have_looped = false;
562 send_full_time_code (0);
563 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
564 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
566 if ((ptw & PostTransportLocate) && get_record_enabled()) {
567 /* capture start has been changed, so save pending state */
568 save_state ("", true);
569 saved = true;
572 /* always try to get rid of this */
574 remove_pending_capture_state ();
576 /* save the current state of things if appropriate */
578 if (did_record && !saved) {
579 save_state (_current_snapshot_name);
582 if (ptw & PostTransportDuration) {
583 DurationChanged (); /* EMIT SIGNAL */
586 if (ptw & PostTransportStop) {
587 _play_range = false;
588 play_loop = false;
591 // can't cast away volatile so copy and emit that
592 nframes64_t tframe = _transport_frame;
593 PositionChanged (tframe); /* EMIT SIGNAL */
594 TransportStateChange (); /* EMIT SIGNAL */
596 /* and start it up again if relevant */
598 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
599 request_transport_speed (1.0);
600 pending_locate_roll = false;
604 void
605 Session::check_declick_out ()
607 bool locate_required = transport_sub_state & PendingLocate;
609 /* this is called after a process() iteration. if PendingDeclickOut was set,
610 it means that we were waiting to declick the output (which has just been
611 done) before doing something else. this is where we do that "something else".
613 note: called from the audio thread.
616 if (transport_sub_state & PendingDeclickOut) {
618 if (locate_required) {
619 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
620 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
621 } else {
622 stop_transport (pending_abort);
623 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
628 void
629 Session::unset_play_loop ()
631 play_loop = false;
632 clear_events (SessionEvent::AutoLoop);
634 // set all diskstreams to NOT use internal looping
635 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
636 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
637 if (!(*i)->hidden()) {
638 (*i)->set_loop (0);
643 void
644 Session::set_play_loop (bool yn)
646 /* Called from event-handling context */
648 Location *loc;
650 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
651 /* nothing to do, or can't change loop status while recording */
652 return;
655 set_dirty();
657 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
658 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
659 "Recommend changing the configured options"), PROGRAM_NAME)
660 << endmsg;
661 return;
664 if (yn) {
666 play_loop = true;
668 if (loc) {
670 unset_play_range ();
672 if (Config->get_seamless_loop()) {
673 // set all diskstreams to use internal looping
674 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
675 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
676 if (!(*i)->hidden()) {
677 (*i)->set_loop (loc);
681 else {
682 // set all diskstreams to NOT use internal looping
683 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
684 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
685 if (!(*i)->hidden()) {
686 (*i)->set_loop (0);
691 /* put the loop event into the event list */
693 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
694 merge_event (event);
696 /* locate to start of loop and roll. If doing seamless loop, force a
697 locate+buffer refill even if we are positioned there already.
700 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
703 } else {
705 unset_play_loop ();
708 TransportStateChange ();
710 void
711 Session::flush_all_inserts ()
713 boost::shared_ptr<RouteList> r = routes.reader ();
715 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
716 (*i)->flush_processors ();
720 void
721 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
723 if (synced_to_jack()) {
725 double sp;
726 nframes64_t pos;
728 _slave->speed_and_position (sp, pos);
730 if (target_frame != pos) {
732 /* tell JACK to change transport position, and we will
733 follow along later in ::follow_slave()
736 _engine.transport_locate (target_frame);
738 if (sp != 1.0f && with_roll) {
739 _engine.transport_start ();
744 } else {
745 locate (target_frame, with_roll, with_flush, with_loop, force);
750 Session::micro_locate (nframes_t distance)
752 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
754 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
755 if (!(*i)->can_internal_playback_seek (distance)) {
756 return -1;
760 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
761 (*i)->internal_playback_seek (distance);
764 _transport_frame += distance;
765 return 0;
768 void
769 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
771 if (actively_recording() && !with_loop) {
772 return;
775 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
776 if (with_roll) {
777 set_transport_speed (1.0, false);
779 loop_changing = false;
780 return;
783 // Update Timecode time
784 // [DR] FIXME: find out exactly where this should go below
785 _transport_frame = target_frame;
786 timecode_time(_transport_frame, transmitting_timecode_time);
787 outbound_mtc_timecode_frame = _transport_frame;
788 next_quarter_frame_to_send = 0;
790 if (_transport_speed && (!with_loop || loop_changing)) {
791 /* schedule a declick. we'll be called again when its done */
793 if (!(transport_sub_state & PendingDeclickOut)) {
794 transport_sub_state |= (PendingDeclickOut|PendingLocate);
795 pending_locate_frame = target_frame;
796 pending_locate_roll = with_roll;
797 pending_locate_flush = with_flush;
798 return;
802 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
803 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
806 if (force || !with_loop || loop_changing) {
808 PostTransportWork todo = PostTransportLocate;
810 if (with_roll) {
811 todo = PostTransportWork (todo | PostTransportRoll);
814 add_post_transport_work (todo);
815 _butler->schedule_transport_work ();
817 } else {
819 /* this is functionally what clear_clicks() does but with a tentative lock */
821 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
823 if (clickm.locked()) {
825 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
826 delete *i;
829 clicks.clear ();
833 if (with_roll) {
834 /* switch from input if we're going to roll */
835 if (Config->get_monitoring_model() == HardwareMonitoring) {
837 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
839 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
840 if ((*i)->record_enabled ()) {
841 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
842 (*i)->monitor_input (!config.get_auto_input());
846 } else {
847 /* otherwise we're going to stop, so do the opposite */
848 if (Config->get_monitoring_model() == HardwareMonitoring) {
849 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
851 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
852 if ((*i)->record_enabled ()) {
853 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
854 (*i)->monitor_input (true);
860 /* cancel looped playback if transport pos outside of loop range */
861 if (play_loop) {
862 Location* al = _locations.auto_loop_location();
864 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
865 // cancel looping directly, this is called from event handling context
866 set_play_loop (false);
868 else if (al && _transport_frame == al->start()) {
869 if (with_loop) {
870 // this is only necessary for seamless looping
872 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
874 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
875 if ((*i)->record_enabled ()) {
876 // tell it we've looped, so it can deal with the record state
877 (*i)->transport_looped(_transport_frame);
881 have_looped = true;
882 TransportLooped(); // EMIT SIGNAL
886 loop_changing = false;
888 _send_timecode_update = true;
890 Located (); /* EMIT SIGNAL */
893 /** Set the transport speed.
894 * @param speed New speed
895 * @param abort
897 void
898 Session::set_transport_speed (double speed, bool abort, bool clear_state)
900 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));
902 if (_transport_speed == speed) {
903 return;
906 _target_transport_speed = fabs(speed);
908 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
909 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
912 if (speed > 0) {
913 speed = min (8.0, speed);
914 } else if (speed < 0) {
915 speed = max (-8.0, speed);
918 if (transport_rolling() && speed == 0.0) {
920 /* we are rolling and we want to stop */
922 if (Config->get_monitoring_model() == HardwareMonitoring)
924 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
926 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
927 if ((*i)->record_enabled ()) {
928 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
929 (*i)->monitor_input (true);
934 if (synced_to_jack ()) {
935 if (clear_state) {
936 /* do this here because our response to the slave won't
937 take care of it.
939 _play_range = false;
940 unset_play_loop ();
942 _engine.transport_stop ();
943 } else {
944 stop_transport (abort);
947 } else if (transport_stopped() && speed == 1.0) {
949 /* we are stopped and we want to start rolling at speed 1 */
951 if (Config->get_monitoring_model() == HardwareMonitoring) {
953 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
955 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
956 if (config.get_auto_input() && (*i)->record_enabled ()) {
957 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
958 (*i)->monitor_input (false);
963 if (synced_to_jack()) {
964 _engine.transport_start ();
965 } else {
966 start_transport ();
969 } else {
971 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
972 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
973 PROGRAM_NAME)
974 << endmsg;
975 return;
978 if (actively_recording()) {
979 return;
982 if (speed > 0.0 && _transport_frame == current_end_frame()) {
983 return;
986 if (speed < 0.0 && _transport_frame == 0) {
987 return;
990 clear_clicks ();
992 /* if we are reversing relative to the current speed, or relative to the speed
993 before the last stop, then we have to do extra work.
996 PostTransportWork todo = PostTransportWork (0);
998 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
999 todo = PostTransportWork (todo | PostTransportReverse);
1002 _last_transport_speed = _transport_speed;
1003 _transport_speed = speed;
1005 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1006 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1007 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1008 todo = PostTransportWork (todo | PostTransportSpeed);
1009 break;
1013 if (todo) {
1014 add_post_transport_work (todo);
1015 _butler->schedule_transport_work ();
1021 /** Stop the transport. */
1022 void
1023 Session::stop_transport (bool abort, bool clear_state)
1025 if (_transport_speed == 0.0f) {
1026 return;
1029 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1031 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1033 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1034 (*i)->prepare_to_stop (_transport_frame);
1037 /* we need to capture the audio that has still not yet been received by the system
1038 at the time the stop is requested, so we have to roll past that time.
1040 we want to declick before stopping, so schedule the autostop for one
1041 block before the actual end. we'll declick in the subsequent block,
1042 and then we'll really be stopped.
1045 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1046 _transport_frame + _worst_output_latency - current_block_size,
1047 0, 0, abort);
1049 merge_event (ev);
1050 transport_sub_state |= StopPendingCapture;
1051 pending_abort = abort;
1052 return;
1056 if ((transport_sub_state & PendingDeclickOut) == 0) {
1058 if (!(transport_sub_state & StopPendingCapture)) {
1059 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1061 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1062 (*i)->prepare_to_stop (_transport_frame);
1066 transport_sub_state |= PendingDeclickOut;
1067 /* we'll be called again after the declick */
1068 pending_abort = abort;
1069 return;
1072 realtime_stop (abort, clear_state);
1073 _butler->schedule_transport_work ();
1076 void
1077 Session::start_transport ()
1079 _last_roll_location = _transport_frame;
1080 have_looped = false;
1082 /* if record status is Enabled, move it to Recording. if its
1083 already Recording, move it to Disabled.
1086 switch (record_status()) {
1087 case Enabled:
1088 if (!config.get_punch_in()) {
1089 enable_record ();
1091 break;
1093 case Recording:
1094 if (!play_loop) {
1095 disable_record (false);
1097 break;
1099 default:
1100 break;
1103 transport_sub_state |= PendingDeclickIn;
1105 _transport_speed = 1.0;
1106 _target_transport_speed = 1.0;
1108 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1109 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1110 (*i)->realtime_set_speed ((*i)->speed(), true);
1113 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
1115 TransportStateChange (); /* EMIT SIGNAL */
1118 /** Do any transport work in the audio thread that needs to be done after the
1119 * transport thread is finished. Audio thread, realtime safe.
1121 void
1122 Session::post_transport ()
1124 PostTransportWork ptw = post_transport_work ();
1126 if (ptw & PostTransportAudition) {
1127 if (auditioner && auditioner->auditioning()) {
1128 process_function = &Session::process_audition;
1129 } else {
1130 process_function = &Session::process_with_events;
1134 if (ptw & PostTransportStop) {
1136 transport_sub_state = 0;
1139 if (ptw & PostTransportLocate) {
1141 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1142 start_transport ();
1144 } else {
1145 transport_sub_state = 0;
1149 set_next_event ();
1150 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1151 know were handled ?
1153 set_post_transport_work (PostTransportWork (0));
1156 void
1157 Session::reset_rf_scale (nframes_t motion)
1159 cumulative_rf_motion += motion;
1161 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1162 rf_scale = 1;
1163 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1164 rf_scale = 4;
1165 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1166 rf_scale = 10;
1167 } else {
1168 rf_scale = 100;
1171 if (motion != 0) {
1172 set_dirty();
1176 void
1177 Session::use_sync_source (Slave* new_slave)
1179 /* Runs in process() context */
1181 bool non_rt_required = false;
1183 /* XXX this deletion is problematic because we're in RT context */
1185 delete _slave;
1186 _slave = new_slave;
1188 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1189 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1190 if (!(*i)->hidden()) {
1191 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1192 non_rt_required = true;
1194 (*i)->set_slaved (_slave != 0);
1198 if (non_rt_required) {
1199 add_post_transport_work (PostTransportSpeed);
1200 _butler->schedule_transport_work ();
1203 set_dirty();
1206 void
1207 Session::drop_sync_source ()
1209 request_sync_source (0);
1212 void
1213 Session::switch_to_sync_source (SyncSource src)
1215 Slave* new_slave;
1217 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1219 switch (src) {
1220 case MTC:
1221 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1222 return;
1225 if (_mtc_port) {
1226 try {
1227 new_slave = new MTC_Slave (*this, *_mtc_port);
1230 catch (failed_constructor& err) {
1231 return;
1234 } else {
1235 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1236 return;
1238 break;
1240 case MIDIClock:
1241 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1242 return;
1245 if (_midi_clock_port) {
1246 try {
1247 new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1250 catch (failed_constructor& err) {
1251 return;
1254 } else {
1255 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1256 return;
1258 break;
1260 case JACK:
1261 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1262 return;
1265 new_slave = new JACK_Slave (_engine.jack());
1266 break;
1268 default:
1269 new_slave = 0;
1270 break;
1273 request_sync_source (new_slave);
1276 void
1277 Session::reverse_diskstream_buffers ()
1279 add_post_transport_work (PostTransportReverse);
1280 _butler->schedule_transport_work ();
1283 void
1284 Session::set_diskstream_speed (Diskstream* stream, double speed)
1286 if (stream->realtime_set_speed (speed, false)) {
1287 add_post_transport_work (PostTransportSpeed);
1288 _butler->schedule_transport_work ();
1289 set_dirty ();
1293 void
1294 Session::unset_play_range ()
1296 _play_range = false;
1297 _clear_event_type (SessionEvent::RangeStop);
1298 _clear_event_type (SessionEvent::RangeLocate);
1301 void
1302 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1304 SessionEvent* ev;
1306 /* Called from event-processing context */
1308 unset_play_range ();
1310 if (range.empty()) {
1311 /* _play_range set to false in unset_play_range()
1313 if (!leave_rolling) {
1314 /* stop transport */
1315 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1316 merge_event (ev);
1318 return;
1321 _play_range = true;
1323 /* cancel loop play */
1324 unset_play_loop ();
1326 list<AudioRange>::size_type sz = range.size();
1328 if (sz > 1) {
1330 list<AudioRange>::iterator i = range.begin();
1331 list<AudioRange>::iterator next;
1333 while (i != range.end()) {
1335 next = i;
1336 ++next;
1338 /* locating/stopping is subject to delays for declicking.
1341 nframes_t requested_frame = (*i).end;
1343 if (requested_frame > current_block_size) {
1344 requested_frame -= current_block_size;
1345 } else {
1346 requested_frame = 0;
1349 if (next == range.end()) {
1350 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1351 } else {
1352 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1355 merge_event (ev);
1357 i = next;
1360 } else if (sz == 1) {
1362 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1363 merge_event (ev);
1367 /* save range so we can do auto-return etc. */
1369 current_audio_range = range;
1371 /* now start rolling at the right place */
1373 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1374 merge_event (ev);
1376 TransportStateChange ();
1379 void
1380 Session::request_bounded_roll (nframes_t start, nframes_t end)
1382 AudioRange ar (start, end, 0);
1383 list<AudioRange> lar;
1385 lar.push_back (ar);
1386 request_play_range (&lar, true);
1388 void
1389 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1391 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1392 ev->target2_frame = start;
1393 queue_event (ev);
1396 void
1397 Session::engine_halted ()
1399 bool ignored;
1401 /* there will be no more calls to process(), so
1402 we'd better clean up for ourselves, right now.
1404 but first, make sure the butler is out of
1405 the picture.
1408 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1409 set_post_transport_work (PostTransportWork (0));
1410 _butler->stop ();
1412 realtime_stop (false, true);
1413 non_realtime_stop (false, 0, ignored);
1414 transport_sub_state = 0;
1416 TransportStateChange (); /* EMIT SIGNAL */
1420 void
1421 Session::xrun_recovery ()
1423 // can't cast away volatile so copy and emit that
1424 nframes64_t tframe = _transport_frame;
1425 Xrun (tframe); //EMIT SIGNAL
1427 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1429 /* it didn't actually halt, but we need
1430 to handle things in the same way.
1433 engine_halted();
1437 void
1438 Session::route_processors_changed (RouteProcessorChange c)
1440 if (c.type == RouteProcessorChange::MeterPointChange) {
1441 return;
1444 update_latency_compensation (false, false);
1445 resort_routes ();
1448 void
1449 Session::update_latency_compensation (bool with_stop, bool abort)
1451 bool update_jack = false;
1452 PostTransportWork ptw;
1454 if (_state_of_the_state & Deletion) {
1455 return;
1458 _worst_track_latency = 0;
1459 ptw = post_transport_work();
1461 #undef DEBUG_LATENCY
1462 #ifdef DEBUG_LATENCY
1463 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1464 #endif
1466 boost::shared_ptr<RouteList> r = routes.reader ();
1468 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1470 if (with_stop) {
1471 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1474 nframes_t old_latency = (*i)->output()->signal_latency ();
1475 nframes_t track_latency = (*i)->update_total_latency ();
1477 if (old_latency != track_latency) {
1478 (*i)->input()->update_port_total_latencies ();
1479 (*i)->output()->update_port_total_latencies ();
1480 update_jack = true;
1483 if (!(*i)->is_hidden() && ((*i)->active())) {
1484 _worst_track_latency = max (_worst_track_latency, track_latency);
1488 if (update_jack) {
1489 _engine.update_total_latencies ();
1492 #ifdef DEBUG_LATENCY
1493 cerr << "\tworst was " << _worst_track_latency << endl;
1494 #endif
1496 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1497 (*i)->set_latency_delay (_worst_track_latency);
1500 set_worst_io_latencies ();
1502 /* reflect any changes in latencies into capture offsets
1505 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1507 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1508 (*i)->set_capture_offset ();
1512 void
1513 Session::allow_auto_play (bool yn)
1515 auto_play_legal = yn;
1518 void
1519 Session::reset_jack_connection (jack_client_t* jack)
1521 JACK_Slave* js;
1523 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1524 js->reset_client (jack);
1528 bool
1529 Session::maybe_stop (nframes_t limit)
1531 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1532 if (synced_to_jack () && config.get_jack_time_master ()) {
1533 _engine.transport_stop ();
1534 } else if (!synced_to_jack ()) {
1535 stop_transport ();
1537 return true;
1539 return false;