2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "pbd/error.h"
27 #include "pbd/enumwriter.h"
28 #include "pbd/pthread_utils.h"
29 #include "pbd/memento_command.h"
31 #include "midi++/mmc.h"
32 #include "midi++/port.h"
34 #include "ardour/ardour.h"
35 #include "ardour/audio_diskstream.h"
36 #include "ardour/audioengine.h"
37 #include "ardour/auditioner.h"
38 #include "ardour/butler.h"
39 #include "ardour/debug.h"
40 #include "ardour/location.h"
41 #include "ardour/session.h"
42 #include "ardour/slave.h"
47 using namespace ARDOUR
;
51 Session::add_post_transport_work (PostTransportWork ptw
)
53 PostTransportWork oldval
;
54 PostTransportWork newval
;
58 oldval
= (PostTransportWork
) g_atomic_int_get (&_post_transport_work
);
59 newval
= PostTransportWork (oldval
| ptw
);
60 if (g_atomic_int_compare_and_exchange (&_post_transport_work
, oldval
, newval
)) {
66 error
<< "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg
;
70 Session::request_input_change_handling ()
72 if (!(_state_of_the_state
& (InitialConnecting
|Deletion
))) {
73 SessionEvent
* ev
= new SessionEvent (SessionEvent::InputConfigurationChange
, SessionEvent::Add
, SessionEvent::Immediate
, 0, 0.0);
79 Session::request_sync_source (Slave
* new_slave
)
81 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetSyncSource
, SessionEvent::Add
, SessionEvent::Immediate
, 0, 0.0);
84 seamless
= Config
->get_seamless_loop ();
86 if (dynamic_cast<JACK_Slave
*>(new_slave
)) {
87 /* JACK cannot support seamless looping at present */
88 Config
->set_seamless_loop (false);
90 /* reset to whatever the value was before we last switched slaves */
91 Config
->set_seamless_loop (_was_seamless
);
94 /* save value of seamless from before the switch */
95 _was_seamless
= seamless
;
97 ev
->slave
= new_slave
;
102 Session::request_transport_speed (double speed
)
104 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetTransportSpeed
, SessionEvent::Add
, SessionEvent::Immediate
, 0, speed
);
105 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request transport speed = %1\n", speed
));
110 Session::request_diskstream_speed (Diskstream
& ds
, double speed
)
112 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetDiskstreamSpeed
, SessionEvent::Add
, SessionEvent::Immediate
, 0, speed
);
118 Session::request_stop (bool abort
, bool clear_state
)
120 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetTransportSpeed
, SessionEvent::Add
, SessionEvent::Immediate
, 0, 0.0, abort
, clear_state
);
121 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort
, clear_state
));
126 Session::request_locate (nframes_t target_frame
, bool with_roll
)
128 SessionEvent
*ev
= new SessionEvent (with_roll
? SessionEvent::LocateRoll
: SessionEvent::Locate
, SessionEvent::Add
, SessionEvent::Immediate
, target_frame
, 0, false);
129 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request locate to %1\n", target_frame
));
134 Session::force_locate (nframes64_t target_frame
, bool with_roll
)
136 SessionEvent
*ev
= new SessionEvent (with_roll
? SessionEvent::LocateRoll
: SessionEvent::Locate
, SessionEvent::Add
, SessionEvent::Immediate
, target_frame
, 0, true);
137 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request forced locate to %1\n", target_frame
));
142 Session::request_play_loop (bool yn
, bool leave_rolling
)
145 Location
*location
= _locations
.auto_loop_location();
147 if (location
== 0 && yn
) {
148 error
<< _("Cannot loop - no loop range defined")
153 ev
= new SessionEvent (SessionEvent::SetLoop
, SessionEvent::Add
, SessionEvent::Immediate
, 0, (leave_rolling
? 1.0 : 0.0), yn
);
154 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn
, leave_rolling
));
157 if (!leave_rolling
&& !yn
&& Config
->get_seamless_loop() && transport_rolling()) {
158 // request an immediate locate to refresh the diskstreams
159 // after disabling looping
160 request_locate (_transport_frame
-1, false);
165 Session::request_play_range (list
<AudioRange
>* range
, bool leave_rolling
)
167 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetPlayAudioRange
, SessionEvent::Add
, SessionEvent::Immediate
, 0, (leave_rolling
? 1.0 : 0.0));
169 ev
->audio_range
= *range
;
171 ev
->audio_range
.clear ();
173 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling
));
178 Session::realtime_stop (bool abort
, bool clear_state
)
180 DEBUG_TRACE (DEBUG::Transport
, "realtime stop\n");
181 PostTransportWork todo
= PostTransportWork (0);
183 /* assume that when we start, we'll be moving forwards */
185 // FIXME: where should this really be? [DR]
186 //send_full_time_code();
187 deliver_mmc (MIDI::MachineControl::cmdStop
, 0);
188 deliver_mmc (MIDI::MachineControl::cmdLocate
, _transport_frame
);
190 if (_transport_speed
< 0.0f
) {
191 todo
= (PostTransportWork (todo
| PostTransportStop
| PostTransportReverse
));
193 todo
= PostTransportWork (todo
| PostTransportStop
);
196 if (actively_recording()) {
198 /* move the transport position back to where the
199 request for a stop was noticed. we rolled
200 past that point to pick up delayed input (and/or to delick)
203 if (_worst_output_latency
> current_block_size
) {
204 /* we rolled past the stop point to pick up data that had
205 not yet arrived. move back to where the stop occured.
207 decrement_transport_position (current_block_size
+ (_worst_output_latency
- current_block_size
));
209 decrement_transport_position (current_block_size
);
212 /* the duration change is not guaranteed to have happened, but is likely */
214 todo
= PostTransportWork (todo
| PostTransportDuration
);
218 todo
= PostTransportWork (todo
| PostTransportAbort
);
222 todo
= PostTransportWork (todo
| PostTransportClearSubstate
);
226 add_post_transport_work (todo
);
229 _clear_event_type (SessionEvent::StopOnce
);
230 _clear_event_type (SessionEvent::RangeStop
);
231 _clear_event_type (SessionEvent::RangeLocate
);
233 /* 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);
249 Session::butler_transport_work ()
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
);
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
) {
282 cumulative_rf_motion
= 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
);
302 if (ptw
& PostTransportLocate
) {
303 non_realtime_locate ();
306 if (ptw
& PostTransportStop
) {
307 non_realtime_stop (ptw
& PostTransportAbort
, on_entry
, finished
);
309 g_atomic_int_dec_and_test (&_butler
->should_do_transport_work
);
314 if (ptw
& PostTransportOverWrite
) {
315 non_realtime_overwrite (on_entry
, finished
);
317 g_atomic_int_dec_and_test (&_butler
->should_do_transport_work
);
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"));
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 ();
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
)) {
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
);
370 Session::non_realtime_stop (bool abort
, int on_entry
, bool& finished
)
376 PostTransportWork ptw
= post_transport_work();
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) {
390 /* stop and locate are merged here because they share a lot of common stuff */
393 now
= localtime (&xnow
);
396 auditioner
->cancel_audition ();
400 cumulative_rf_motion
= 0;
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 */
420 } else if (_transport_frame
> loc
->end()) {
422 /* stopped recording after the current end, extend it */
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);
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) ||
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
;
488 if (config
.get_auto_return()) {
492 /* don't try to handle loop play when synced to JACK */
494 if (!synced_to_jack()) {
496 Location
*location
= _locations
.auto_loop_location();
499 _transport_frame
= location
->start();
501 _transport_frame
= _last_roll_location
;
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
;
517 /* regular auto-return */
519 _transport_frame
= _last_roll_location
;
525 _requested_return_frame
= -1;
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
) {
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
)) {
555 /* we will be back */
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);
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
) {
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;
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
);
622 stop_transport (pending_abort
);
623 transport_sub_state
&= ~(PendingDeclickOut
|PendingLocate
);
629 Session::unset_play_loop ()
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()) {
644 Session::set_play_loop (bool yn
)
646 /* Called from event-handling context */
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 */
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
)
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
);
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()) {
691 /* put the loop event into the event list */
693 SessionEvent
* event
= new SessionEvent (SessionEvent::AutoLoop
, SessionEvent::Replace
, loc
->end(), loc
->start(), 0.0f
);
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());
708 TransportStateChange ();
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 ();
721 Session::start_locate (nframes64_t target_frame
, bool with_roll
, bool with_flush
, bool with_loop
, bool force
)
723 if (synced_to_jack()) {
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 ();
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
)) {
760 for (DiskstreamList::iterator i
= dsl
->begin(); i
!= dsl
->end(); ++i
) {
761 (*i
)->internal_playback_seek (distance
);
764 _transport_frame
+= distance
;
769 Session::locate (nframes64_t target_frame
, bool with_roll
, bool with_flush
, bool with_loop
, bool force
)
771 if (actively_recording() && !with_loop
) {
775 if (!force
&& _transport_frame
== target_frame
&& !loop_changing
&& !with_loop
) {
777 set_transport_speed (1.0, false);
779 loop_changing
= false;
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
;
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
;
811 todo
= PostTransportWork (todo
| PostTransportRoll
);
814 add_post_transport_work (todo
);
815 _butler
->schedule_transport_work ();
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
) {
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());
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 */
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()) {
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
);
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
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
) {
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.
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 ()) {
936 /* do this here because our response to the slave won't
942 _engine
.transport_stop ();
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 ();
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"),
978 if (actively_recording()) {
982 if (speed
> 0.0 && _transport_frame
== current_end_frame()) {
986 if (speed
< 0.0 && _transport_frame
== 0) {
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
);
1014 add_post_transport_work (todo
);
1015 _butler
->schedule_transport_work ();
1021 /** Stop the transport. */
1023 Session::stop_transport (bool abort
, bool clear_state
)
1025 if (_transport_speed
== 0.0f
) {
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
,
1050 transport_sub_state
|= StopPendingCapture
;
1051 pending_abort
= abort
;
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
;
1072 realtime_stop (abort
, clear_state
);
1073 _butler
->schedule_transport_work ();
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()) {
1088 if (!config
.get_punch_in()) {
1095 disable_record (false);
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.
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
;
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
)) {
1145 transport_sub_state
= 0;
1150 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1153 set_post_transport_work (PostTransportWork (0));
1157 Session::reset_rf_scale (nframes_t motion
)
1159 cumulative_rf_motion
+= motion
;
1161 if (cumulative_rf_motion
< 4 * _current_frame_rate
) {
1163 } else if (cumulative_rf_motion
< 8 * _current_frame_rate
) {
1165 } else if (cumulative_rf_motion
< 16 * _current_frame_rate
) {
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 */
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 ();
1207 Session::drop_sync_source ()
1209 request_sync_source (0);
1213 Session::switch_to_sync_source (SyncSource src
)
1217 DEBUG_TRACE (DEBUG::Slave
, string_compose ("Setting up sync source %1\n", enum_2_string (src
)));
1221 if (_slave
&& dynamic_cast<MTC_Slave
*>(_slave
)) {
1227 new_slave
= new MTC_Slave (*this, *_mtc_port
);
1230 catch (failed_constructor
& err
) {
1235 error
<< _("No MTC port defined: MTC slaving is impossible.") << endmsg
;
1241 if (_slave
&& dynamic_cast<MIDIClock_Slave
*>(_slave
)) {
1245 if (_midi_clock_port
) {
1247 new_slave
= new MIDIClock_Slave (*this, *_midi_clock_port
, 24);
1250 catch (failed_constructor
& err
) {
1255 error
<< _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg
;
1261 if (_slave
&& dynamic_cast<JACK_Slave
*>(_slave
)) {
1265 new_slave
= new JACK_Slave (_engine
.jack());
1273 request_sync_source (new_slave
);
1277 Session::reverse_diskstream_buffers ()
1279 add_post_transport_work (PostTransportReverse
);
1280 _butler
->schedule_transport_work ();
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 ();
1294 Session::unset_play_range ()
1296 _play_range
= false;
1297 _clear_event_type (SessionEvent::RangeStop
);
1298 _clear_event_type (SessionEvent::RangeLocate
);
1302 Session::set_play_range (list
<AudioRange
>& range
, bool leave_rolling
)
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);
1323 /* cancel loop play */
1326 list
<AudioRange
>::size_type sz
= range
.size();
1330 list
<AudioRange
>::iterator i
= range
.begin();
1331 list
<AudioRange
>::iterator next
;
1333 while (i
!= range
.end()) {
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
;
1346 requested_frame
= 0;
1349 if (next
== range
.end()) {
1350 ev
= new SessionEvent (SessionEvent::RangeStop
, SessionEvent::Add
, requested_frame
, 0, 0.0f
);
1352 ev
= new SessionEvent (SessionEvent::RangeLocate
, SessionEvent::Add
, requested_frame
, (*next
).start
, 0.0f
);
1360 } else if (sz
== 1) {
1362 ev
= new SessionEvent (SessionEvent::RangeStop
, SessionEvent::Add
, range
.front().end
, 0, 0.0f
);
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);
1376 TransportStateChange ();
1380 Session::request_bounded_roll (nframes_t start
, nframes_t end
)
1382 AudioRange
ar (start
, end
, 0);
1383 list
<AudioRange
> lar
;
1386 request_play_range (&lar
, true);
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
;
1397 Session::engine_halted ()
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
1408 g_atomic_int_set (&_butler
->should_do_transport_work
, 0);
1409 set_post_transport_work (PostTransportWork (0));
1412 realtime_stop (false, true);
1413 non_realtime_stop (false, 0, ignored
);
1414 transport_sub_state
= 0;
1416 TransportStateChange (); /* EMIT SIGNAL */
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.
1438 Session::route_processors_changed (RouteProcessorChange c
)
1440 if (c
.type
== RouteProcessorChange::MeterPointChange
) {
1444 update_latency_compensation (false, false);
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
) {
1458 _worst_track_latency
= 0;
1459 ptw
= post_transport_work();
1461 #undef DEBUG_LATENCY
1462 #ifdef DEBUG_LATENCY
1463 cerr
<< "\n---------------------------------\nUPDATE LATENCY\n";
1466 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
1468 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
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 ();
1483 if (!(*i
)->is_hidden() && ((*i
)->active())) {
1484 _worst_track_latency
= max (_worst_track_latency
, track_latency
);
1489 _engine
.update_total_latencies ();
1492 #ifdef DEBUG_LATENCY
1493 cerr
<< "\tworst was " << _worst_track_latency
<< endl
;
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 ();
1513 Session::allow_auto_play (bool yn
)
1515 auto_play_legal
= yn
;
1519 Session::reset_jack_connection (jack_client_t
* jack
)
1523 if (_slave
&& ((js
= dynamic_cast<JACK_Slave
*> (_slave
)) != 0)) {
1524 js
->reset_client (jack
);
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 ()) {