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