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 <glibmm/thread.h>
30 #include "pbd/pthread_utils.h"
31 #include "pbd/memento_command.h"
32 #include "pbd/stacktrace.h"
34 #include "midi++/mmc.h"
35 #include "midi++/port.h"
37 #include "ardour/ardour.h"
38 #include "ardour/audio_diskstream.h"
39 #include "ardour/audioengine.h"
40 #include "ardour/auditioner.h"
41 #include "ardour/butler.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 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
82 Session::request_sync_source (SyncSource src)
84 Event* ev = new Event (Event::SetSyncSource, Event::Add, Event::Immediate, 0, 0.0);
87 seamless = Config->get_seamless_loop ();
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->sync_source = src;
105 Session::request_transport_speed (double speed)
107 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
112 Session::request_diskstream_speed (Diskstream& ds, double speed)
114 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
120 Session::request_stop (bool abort, bool clear_state)
122 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort, clear_state);
127 Session::request_locate (nframes_t target_frame, bool with_roll)
129 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
134 Session::force_locate (nframes64_t target_frame, bool with_roll)
136 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
141 Session::request_play_loop (bool yn, bool leave_rolling)
144 Location *location = _locations.auto_loop_location();
146 if (location == 0 && yn) {
147 error << _("Cannot loop - no loop range defined")
152 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
155 if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
156 // request an immediate locate to refresh the diskstreams
157 // after disabling looping
158 request_locate (_transport_frame-1, false);
163 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
165 Event* ev = new Event (Event::SetPlayAudioRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
167 ev->audio_range = *range;
169 ev->audio_range.clear ();
175 Session::realtime_stop (bool abort, bool clear_state)
177 PostTransportWork todo = PostTransportWork (0);
179 /* assume that when we start, we'll be moving forwards */
181 // FIXME: where should this really be? [DR]
182 //send_full_time_code();
183 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
184 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
186 if (_transport_speed < 0.0f) {
187 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
189 todo = PostTransportWork (todo | PostTransportStop);
192 if (actively_recording()) {
194 /* move the transport position back to where the
195 request for a stop was noticed. we rolled
196 past that point to pick up delayed input.
199 decrement_transport_position (_worst_output_latency);
201 /* the duration change is not guaranteed to have happened, but is likely */
203 todo = PostTransportWork (todo | PostTransportDuration);
207 todo = PostTransportWork (todo | PostTransportAbort);
211 todo = PostTransportWork (todo | PostTransportClearSubstate);
215 add_post_transport_work (todo);
218 _clear_event_type (Event::StopOnce);
219 _clear_event_type (Event::RangeStop);
220 _clear_event_type (Event::RangeLocate);
222 disable_record (true);
224 reset_slave_state ();
226 _transport_speed = 0;
227 _target_transport_speed = 0;
229 if (config.get_use_video_sync()) {
230 waiting_for_sync_offset = true;
233 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
237 Session::butler_transport_work ()
241 PostTransportWork ptw;
242 boost::shared_ptr<RouteList> r = routes.reader ();
243 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
245 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
247 ptw = post_transport_work();
248 if (ptw & PostTransportCurveRealloc) {
249 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
250 (*i)->curve_reallocate();
254 if (ptw & PostTransportInputChange) {
255 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
256 (*i)->non_realtime_input_change ();
260 if (ptw & PostTransportSpeed) {
261 non_realtime_set_speed ();
264 if (ptw & PostTransportReverse) {
267 cumulative_rf_motion = 0;
270 /* don't seek if locate will take care of that in non_realtime_stop() */
272 if (!(ptw & PostTransportLocate)) {
274 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
275 if (!(*i)->hidden()) {
276 (*i)->non_realtime_locate (_transport_frame);
278 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
279 /* new request, stop seeking, and start again */
280 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
287 if (ptw & PostTransportLocate) {
288 non_realtime_locate ();
291 if (ptw & PostTransportStop) {
292 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
294 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
299 if (ptw & PostTransportOverWrite) {
300 non_realtime_overwrite (on_entry, finished);
302 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
307 if (ptw & PostTransportAudition) {
308 non_realtime_set_audition ();
311 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
315 Session::non_realtime_set_speed ()
317 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
319 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
320 (*i)->non_realtime_set_speed ();
325 Session::non_realtime_overwrite (int on_entry, bool& finished)
327 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
329 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
330 if ((*i)->pending_overwrite) {
331 (*i)->overwrite_existing_buffers ();
333 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
342 Session::non_realtime_locate ()
344 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
346 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
347 (*i)->non_realtime_locate (_transport_frame);
353 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
359 PostTransportWork ptw = post_transport_work();
364 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
366 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
367 if ((*i)->get_captured_frames () != 0) {
373 /* stop and locate are merged here because they share a lot of common stuff */
376 now = localtime (&xnow);
379 auditioner->cancel_audition ();
383 cumulative_rf_motion = 0;
387 begin_reversible_command ("capture");
389 Location* loc = _locations.end_location();
390 bool change_end = false;
392 if (_transport_frame < loc->end()) {
394 /* stopped recording before current end */
396 if (config.get_end_marker_is_free()) {
398 /* first capture for this session, move end back to where we are */
403 } else if (_transport_frame > loc->end()) {
405 /* stopped recording after the current end, extend it */
411 XMLNode &before = loc->get_state();
412 loc->set_end(_transport_frame);
413 XMLNode &after = loc->get_state();
414 add_command (new MementoCommand<Location>(*loc, &before, &after));
417 config.set_end_marker_is_free (false);
418 _have_captured = true;
421 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
422 (*i)->transport_stopped (*now, xnow, abort);
425 boost::shared_ptr<RouteList> r = routes.reader ();
427 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
428 if (!(*i)->is_hidden()) {
429 (*i)->set_pending_declick (0);
434 commit_reversible_command ();
437 if (_engine.running()) {
438 update_latency_compensation (true, abort);
441 bool const auto_return_enabled =
442 (!config.get_external_sync() && config.get_auto_return());
444 if (auto_return_enabled ||
445 (ptw & PostTransportLocate) ||
446 (_requested_return_frame >= 0) ||
449 if (pending_locate_flush) {
450 flush_all_inserts ();
453 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
454 !(ptw & PostTransportLocate)) {
456 /* no explicit locate queued */
458 bool do_locate = false;
460 if (_requested_return_frame >= 0) {
462 /* explicit return request pre-queued in event list. overrides everything else */
464 cerr << "explicit auto-return to " << _requested_return_frame << endl;
466 _transport_frame = _requested_return_frame;
470 if (config.get_auto_return()) {
474 /* don't try to handle loop play when synced to JACK */
476 if (!synced_to_jack()) {
478 Location *location = _locations.auto_loop_location();
481 _transport_frame = location->start();
483 _transport_frame = _last_roll_location;
488 } else if (_play_range) {
490 /* return to start of range */
492 if (!current_audio_range.empty()) {
493 _transport_frame = current_audio_range.front().start;
499 /* regular auto-return */
501 _transport_frame = _last_roll_location;
507 _requested_return_frame = -1;
510 _engine.transport_locate (_transport_frame);
516 /* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode.
519 if (ptw & PostTransportClearSubstate) {
524 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
527 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
528 if (!(*i)->hidden()) {
529 (*i)->non_realtime_locate (_transport_frame);
531 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
533 /* we will be back */
540 send_full_time_code (0);
541 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
542 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
544 if ((ptw & PostTransportLocate) && get_record_enabled()) {
545 /* capture start has been changed, so save pending state */
546 save_state ("", true);
550 /* always try to get rid of this */
552 remove_pending_capture_state ();
554 /* save the current state of things if appropriate */
556 if (did_record && !saved) {
557 save_state (_current_snapshot_name);
560 if (ptw & PostTransportDuration) {
561 DurationChanged (); /* EMIT SIGNAL */
564 if (ptw & PostTransportStop) {
569 PositionChanged ((nframes64_t) _transport_frame); /* EMIT SIGNAL */
570 TransportStateChange (); /* EMIT SIGNAL */
572 /* and start it up again if relevant */
574 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
575 request_transport_speed (1.0);
576 pending_locate_roll = false;
581 Session::check_declick_out ()
583 bool locate_required = transport_sub_state & PendingLocate;
585 /* this is called after a process() iteration. if PendingDeclickOut was set,
586 it means that we were waiting to declick the output (which has just been
587 done) before doing something else. this is where we do that "something else".
589 note: called from the audio thread.
592 if (transport_sub_state & PendingDeclickOut) {
594 if (locate_required) {
595 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
596 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
598 stop_transport (pending_abort);
599 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
605 Session::unset_play_loop ()
608 clear_events (Event::AutoLoop);
610 // set all diskstreams to NOT use internal looping
611 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
612 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
613 if (!(*i)->hidden()) {
620 Session::set_play_loop (bool yn)
622 /* Called from event-handling context */
626 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
627 /* nothing to do, or can't change loop status while recording */
633 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
634 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
635 "Recommend changing the configured options")
648 if (Config->get_seamless_loop()) {
649 // set all diskstreams to use internal looping
650 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
651 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
652 if (!(*i)->hidden()) {
653 (*i)->set_loop (loc);
658 // set all diskstreams to NOT use internal looping
659 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
660 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
661 if (!(*i)->hidden()) {
667 /* put the loop event into the event list */
669 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
672 /* locate to start of loop and roll. If doing seamless loop, force a
673 locate+buffer refill even if we are positioned there already.
676 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
684 TransportStateChange ();
687 Session::flush_all_inserts ()
689 boost::shared_ptr<RouteList> r = routes.reader ();
691 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
692 (*i)->flush_processors ();
697 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
699 if (synced_to_jack()) {
704 _slave->speed_and_position (sp, pos);
706 if (target_frame != pos) {
708 /* tell JACK to change transport position, and we will
709 follow along later in ::follow_slave()
712 _engine.transport_locate (target_frame);
714 if (sp != 1.0f && with_roll) {
715 _engine.transport_start ();
721 locate (target_frame, with_roll, with_flush, with_loop, force);
726 Session::micro_locate (nframes_t distance)
728 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
730 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
731 if (!(*i)->can_internal_playback_seek (distance)) {
736 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
737 (*i)->internal_playback_seek (distance);
740 _transport_frame += distance;
745 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
747 if (actively_recording() && !with_loop) {
751 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
753 set_transport_speed (1.0, false);
755 loop_changing = false;
759 // Update Timecode time
760 // [DR] FIXME: find out exactly where this should go below
761 _transport_frame = target_frame;
762 timecode_time(_transport_frame, transmitting_timecode_time);
763 outbound_mtc_timecode_frame = _transport_frame;
764 next_quarter_frame_to_send = 0;
766 if (_transport_speed && (!with_loop || loop_changing)) {
767 /* schedule a declick. we'll be called again when its done */
769 if (!(transport_sub_state & PendingDeclickOut)) {
770 transport_sub_state |= (PendingDeclickOut|PendingLocate);
771 pending_locate_frame = target_frame;
772 pending_locate_roll = with_roll;
773 pending_locate_flush = with_flush;
778 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
779 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
782 if (force || !with_loop || loop_changing) {
784 PostTransportWork todo = PostTransportLocate;
787 todo = PostTransportWork (todo | PostTransportRoll);
790 add_post_transport_work (todo);
791 _butler->schedule_transport_work ();
795 /* this is functionally what clear_clicks() does but with a tentative lock */
797 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
799 if (clickm.locked()) {
801 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
810 /* switch from input if we're going to roll */
811 if (Config->get_monitoring_model() == HardwareMonitoring) {
813 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
815 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
816 if ((*i)->record_enabled ()) {
817 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
818 (*i)->monitor_input (!config.get_auto_input());
823 /* otherwise we're going to stop, so do the opposite */
824 if (Config->get_monitoring_model() == HardwareMonitoring) {
825 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
827 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
828 if ((*i)->record_enabled ()) {
829 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
830 (*i)->monitor_input (true);
836 /* cancel looped playback if transport pos outside of loop range */
838 Location* al = _locations.auto_loop_location();
840 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
841 // cancel looping directly, this is called from event handling context
842 set_play_loop (false);
844 else if (al && _transport_frame == al->start()) {
846 // this is only necessary for seamless looping
848 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
850 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
851 if ((*i)->record_enabled ()) {
852 // tell it we've looped, so it can deal with the record state
853 (*i)->transport_looped(_transport_frame);
858 TransportLooped(); // EMIT SIGNAL
862 loop_changing = false;
864 _send_timecode_update = true;
866 Located (); /* EMIT SIGNAL */
869 /** Set the transport speed.
870 * @param speed New speed
874 Session::set_transport_speed (double speed, bool abort, bool clear_state)
876 if (_transport_speed == speed) {
880 _target_transport_speed = fabs(speed);
882 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
883 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
887 speed = min (8.0, speed);
888 } else if (speed < 0) {
889 speed = max (-8.0, speed);
892 if (transport_rolling() && speed == 0.0) {
894 /* we are rolling and we want to stop */
896 if (Config->get_monitoring_model() == HardwareMonitoring)
898 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
900 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
901 if ((*i)->record_enabled ()) {
902 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
903 (*i)->monitor_input (true);
908 if (synced_to_jack ()) {
910 /* do this here because our response to the slave won't
916 _engine.transport_stop ();
918 stop_transport (abort);
921 } else if (transport_stopped() && speed == 1.0) {
923 /* we are stopped and we want to start rolling at speed 1 */
925 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
929 if (Config->get_monitoring_model() == HardwareMonitoring) {
931 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
933 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
934 if (config.get_auto_input() && (*i)->record_enabled ()) {
935 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
936 (*i)->monitor_input (false);
941 if (synced_to_jack()) {
942 _engine.transport_start ();
949 /* if not recording, don't roll forward past end if told to stop there */
951 if (!get_record_enabled() && (speed > 0.0 && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame())) {
955 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
956 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
961 if (actively_recording()) {
965 if (speed > 0.0 && _transport_frame == current_end_frame()) {
969 if (speed < 0.0 && _transport_frame == 0) {
975 /* if we are reversing relative to the current speed, or relative to the speed
976 before the last stop, then we have to do extra work.
979 PostTransportWork todo = PostTransportWork (0);
981 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
982 todo = PostTransportWork (todo | PostTransportReverse);
985 _last_transport_speed = _transport_speed;
986 _transport_speed = speed;
988 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
989 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
990 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
991 todo = PostTransportWork (todo | PostTransportSpeed);
997 add_post_transport_work (todo);
998 _butler->schedule_transport_work ();
1004 /** Stop the transport. */
1006 Session::stop_transport (bool abort, bool clear_state)
1008 if (_transport_speed == 0.0f) {
1012 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
1013 _worst_output_latency > current_block_size)
1016 /* we need to capture the audio that has still not yet been received by the system
1017 at the time the stop is requested, so we have to roll past that time.
1019 we want to declick before stopping, so schedule the autostop for one
1020 block before the actual end. we'll declick in the subsequent block,
1021 and then we'll really be stopped.
1024 Event *ev = new Event (Event::StopOnce, Event::Replace,
1025 _transport_frame + _worst_output_latency - current_block_size,
1029 transport_sub_state |= StopPendingCapture;
1030 pending_abort = abort;
1035 if ((transport_sub_state & PendingDeclickOut) == 0) {
1036 transport_sub_state |= PendingDeclickOut;
1037 /* we'll be called again after the declick */
1038 pending_abort = abort;
1042 realtime_stop (abort, clear_state);
1043 _butler->schedule_transport_work ();
1047 Session::start_transport ()
1049 _last_roll_location = _transport_frame;
1050 have_looped = false;
1052 /* if record status is Enabled, move it to Recording. if its
1053 already Recording, move it to Disabled.
1056 switch (record_status()) {
1058 if (!config.get_punch_in()) {
1065 disable_record (false);
1073 transport_sub_state |= PendingDeclickIn;
1075 _transport_speed = 1.0;
1076 _target_transport_speed = 1.0;
1078 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1079 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1080 (*i)->realtime_set_speed ((*i)->speed(), true);
1083 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
1085 TransportStateChange (); /* EMIT SIGNAL */
1088 /** Do any transport work in the audio thread that needs to be done after the
1089 * transport thread is finished. Audio thread, realtime safe.
1092 Session::post_transport ()
1094 PostTransportWork ptw = post_transport_work ();
1096 if (ptw & PostTransportAudition) {
1097 if (auditioner && auditioner->active()) {
1098 process_function = &Session::process_audition;
1100 process_function = &Session::process_with_events;
1104 if (ptw & PostTransportStop) {
1106 transport_sub_state = 0;
1109 if (ptw & PostTransportLocate) {
1111 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1115 transport_sub_state = 0;
1120 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1123 set_post_transport_work (PostTransportWork (0));
1127 Session::reset_rf_scale (nframes_t motion)
1129 cumulative_rf_motion += motion;
1131 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1133 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1135 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1147 Session::drop_sync_source ()
1149 bool non_rt_required = false;
1151 if (_transport_speed) {
1152 error << _("please stop the transport before adjusting slave settings") << endmsg;
1159 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1160 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1161 if (!(*i)->hidden()) {
1162 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1163 non_rt_required = true;
1165 (*i)->set_slaved (0);
1169 if (non_rt_required) {
1170 add_post_transport_work (PostTransportSpeed);
1171 _butler->schedule_transport_work ();
1178 Session::use_sync_source (SyncSource src)
1180 bool reverse = false;
1181 bool non_rt_required = false;
1183 if (_transport_speed) {
1184 error << _("please stop the transport before adjusting slave settings") << endmsg;
1195 _slave = new MTC_Slave (*this, *_mtc_port);
1198 catch (failed_constructor& err) {
1203 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1209 if (_midi_clock_port) {
1211 _slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
1214 catch (failed_constructor& err) {
1219 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1225 _slave = new JACK_Slave (_engine.jack());
1230 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1231 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1232 if (!(*i)->hidden()) {
1233 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1234 non_rt_required = true;
1236 (*i)->set_slaved (_slave);
1241 reverse_diskstream_buffers ();
1244 if (non_rt_required) {
1245 add_post_transport_work (PostTransportSpeed);
1246 _butler->schedule_transport_work ();
1253 Session::reverse_diskstream_buffers ()
1255 add_post_transport_work (PostTransportReverse);
1256 _butler->schedule_transport_work ();
1260 Session::set_diskstream_speed (Diskstream* stream, double speed)
1262 if (stream->realtime_set_speed (speed, false)) {
1263 add_post_transport_work (PostTransportSpeed);
1264 _butler->schedule_transport_work ();
1270 Session::unset_play_range ()
1272 _play_range = false;
1273 _clear_event_type (Event::RangeStop);
1274 _clear_event_type (Event::RangeLocate);
1278 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1282 /* Called from event-processing context */
1284 unset_play_range ();
1286 if (range.empty()) {
1287 /* _play_range set to false in unset_play_range()
1289 if (!leave_rolling) {
1290 /* stop transport */
1291 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1299 /* cancel loop play */
1302 list<AudioRange>::size_type sz = range.size();
1306 list<AudioRange>::iterator i = range.begin();
1307 list<AudioRange>::iterator next;
1309 while (i != range.end()) {
1314 /* locating/stopping is subject to delays for declicking.
1317 nframes_t requested_frame = (*i).end;
1319 if (requested_frame > current_block_size) {
1320 requested_frame -= current_block_size;
1322 requested_frame = 0;
1325 if (next == range.end()) {
1326 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1328 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1336 } else if (sz == 1) {
1338 ev = new Event (Event::RangeStop, Event::Add, range.front().end, 0, 0.0f);
1343 /* save range so we can do auto-return etc. */
1345 current_audio_range = range;
1347 /* now start rolling at the right place */
1349 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, range.front().start, 0.0f, false);
1352 TransportStateChange ();
1356 Session::request_bounded_roll (nframes_t start, nframes_t end)
1358 AudioRange ar (start, end, 0);
1359 list<AudioRange> lar;
1362 request_play_range (&lar, true);
1365 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1367 Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
1368 ev->target2_frame = start;
1373 Session::engine_halted ()
1377 /* there will be no more calls to process(), so
1378 we'd better clean up for ourselves, right now.
1380 but first, make sure the butler is out of
1384 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1385 set_post_transport_work (PostTransportWork (0));
1388 realtime_stop (false, true);
1389 non_realtime_stop (false, 0, ignored);
1390 transport_sub_state = 0;
1392 TransportStateChange (); /* EMIT SIGNAL */
1397 Session::xrun_recovery ()
1399 Xrun ((nframes64_t)_transport_frame); //EMIT SIGNAL
1401 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1403 /* it didn't actually halt, but we need
1404 to handle things in the same way.
1412 Session::update_latency_compensation (bool with_stop, bool abort)
1414 bool update_jack = false;
1415 PostTransportWork ptw;
1417 if (_state_of_the_state & Deletion) {
1421 _worst_track_latency = 0;
1422 ptw = post_transport_work();
1424 #undef DEBUG_LATENCY
1425 #ifdef DEBUG_LATENCY
1426 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1429 boost::shared_ptr<RouteList> r = routes.reader ();
1431 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1434 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1437 nframes_t old_latency = (*i)->output()->signal_latency ();
1438 nframes_t track_latency = (*i)->update_total_latency ();
1440 if (old_latency != track_latency) {
1441 (*i)->input()->update_port_total_latencies ();
1442 (*i)->output()->update_port_total_latencies ();
1446 if (!(*i)->is_hidden() && ((*i)->active())) {
1447 _worst_track_latency = max (_worst_track_latency, track_latency);
1452 _engine.update_total_latencies ();
1455 #ifdef DEBUG_LATENCY
1456 cerr << "\tworst was " << _worst_track_latency << endl;
1459 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1460 (*i)->set_latency_delay (_worst_track_latency);
1463 set_worst_io_latencies ();
1465 /* reflect any changes in latencies into capture offsets
1468 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1470 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1471 (*i)->set_capture_offset ();
1476 Session::allow_auto_play (bool yn)
1478 auto_play_legal = yn;
1482 Session::reset_jack_connection (jack_client_t* jack)
1486 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1487 js->reset_client (jack);
1492 Session::maybe_stop (nframes_t limit)
1494 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1495 if (synced_to_jack () && config.get_jack_time_master ()) {
1496 _engine.transport_stop ();
1497 } else if (!synced_to_jack ()) {