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/audioengine.h"
36 #include "ardour/auditioner.h"
37 #include "ardour/butler.h"
38 #include "ardour/debug.h"
39 #include "ardour/location.h"
40 #include "ardour/session.h"
41 #include "ardour/slave.h"
46 using namespace ARDOUR
;
50 Session::add_post_transport_work (PostTransportWork ptw
)
52 PostTransportWork oldval
;
53 PostTransportWork newval
;
57 oldval
= (PostTransportWork
) g_atomic_int_get (&_post_transport_work
);
58 newval
= PostTransportWork (oldval
| ptw
);
59 if (g_atomic_int_compare_and_exchange (&_post_transport_work
, oldval
, newval
)) {
65 error
<< "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg
;
69 Session::request_input_change_handling ()
71 if (!(_state_of_the_state
& (InitialConnecting
|Deletion
))) {
72 SessionEvent
* ev
= new SessionEvent (SessionEvent::InputConfigurationChange
, SessionEvent::Add
, SessionEvent::Immediate
, 0, 0.0);
78 Session::request_sync_source (Slave
* new_slave
)
80 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetSyncSource
, SessionEvent::Add
, SessionEvent::Immediate
, 0, 0.0);
83 seamless
= Config
->get_seamless_loop ();
85 if (dynamic_cast<JACK_Slave
*>(new_slave
)) {
86 /* JACK cannot support seamless looping at present */
87 Config
->set_seamless_loop (false);
89 /* reset to whatever the value was before we last switched slaves */
90 Config
->set_seamless_loop (_was_seamless
);
93 /* save value of seamless from before the switch */
94 _was_seamless
= seamless
;
96 ev
->slave
= new_slave
;
101 Session::request_transport_speed (double speed
)
103 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetTransportSpeed
, SessionEvent::Add
, SessionEvent::Immediate
, 0, speed
);
104 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request transport speed = %1\n", speed
));
109 Session::request_track_speed (Track
* tr
, double speed
)
111 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetTrackSpeed
, SessionEvent::Add
, SessionEvent::Immediate
, 0, speed
);
117 Session::request_stop (bool abort
, bool clear_state
)
119 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetTransportSpeed
, SessionEvent::Add
, SessionEvent::Immediate
, 0, 0.0, abort
, clear_state
);
120 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort
, clear_state
));
125 Session::request_locate (nframes_t target_frame
, bool with_roll
)
127 SessionEvent
*ev
= new SessionEvent (with_roll
? SessionEvent::LocateRoll
: SessionEvent::Locate
, SessionEvent::Add
, SessionEvent::Immediate
, target_frame
, 0, false);
128 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request locate to %1\n", target_frame
));
133 Session::force_locate (nframes64_t target_frame
, bool with_roll
)
135 SessionEvent
*ev
= new SessionEvent (with_roll
? SessionEvent::LocateRoll
: SessionEvent::Locate
, SessionEvent::Add
, SessionEvent::Immediate
, target_frame
, 0, true);
136 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request forced locate to %1\n", target_frame
));
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 SessionEvent (SessionEvent::SetLoop
, SessionEvent::Add
, SessionEvent::Immediate
, 0, (leave_rolling
? 1.0 : 0.0), yn
);
153 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn
, leave_rolling
));
156 if (!leave_rolling
&& !yn
&& Config
->get_seamless_loop() && transport_rolling()) {
157 // request an immediate locate to refresh the tracks
158 // after disabling looping
159 request_locate (_transport_frame
-1, false);
164 Session::request_play_range (list
<AudioRange
>* range
, bool leave_rolling
)
166 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetPlayAudioRange
, SessionEvent::Add
, SessionEvent::Immediate
, 0, (leave_rolling
? 1.0 : 0.0));
168 ev
->audio_range
= *range
;
170 ev
->audio_range
.clear ();
172 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling
));
177 Session::realtime_stop (bool abort
, bool clear_state
)
179 DEBUG_TRACE (DEBUG::Transport
, "realtime stop\n");
180 PostTransportWork todo
= PostTransportWork (0);
182 /* assume that when we start, we'll be moving forwards */
184 // FIXME: where should this really be? [DR]
185 //send_full_time_code();
188 timecode_time_subframes (_transport_frame
, time
);
190 _mmc
->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop
));
191 _mmc
->send (MIDI::MachineControlCommand (time
));
194 if (_transport_speed
< 0.0f
) {
195 todo
= (PostTransportWork (todo
| PostTransportStop
| PostTransportReverse
));
197 todo
= PostTransportWork (todo
| PostTransportStop
);
200 if (actively_recording()) {
202 /* move the transport position back to where the
203 request for a stop was noticed. we rolled
204 past that point to pick up delayed input (and/or to delick)
207 if (_worst_output_latency
> current_block_size
) {
208 /* we rolled past the stop point to pick up data that had
209 not yet arrived. move back to where the stop occured.
211 decrement_transport_position (current_block_size
+ (_worst_output_latency
- current_block_size
));
213 decrement_transport_position (current_block_size
);
216 /* the duration change is not guaranteed to have happened, but is likely */
218 todo
= PostTransportWork (todo
| PostTransportDuration
);
222 todo
= PostTransportWork (todo
| PostTransportAbort
);
226 todo
= PostTransportWork (todo
| PostTransportClearSubstate
);
230 add_post_transport_work (todo
);
233 _clear_event_type (SessionEvent::StopOnce
);
234 _clear_event_type (SessionEvent::RangeStop
);
235 _clear_event_type (SessionEvent::RangeLocate
);
237 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
238 disable_record (true, (!Config
->get_latched_record_enable() && clear_state
));
240 reset_slave_state ();
242 _transport_speed
= 0;
243 _target_transport_speed
= 0;
245 g_atomic_int_set (&_playback_load
, 100);
246 g_atomic_int_set (&_capture_load
, 100);
248 if (config
.get_use_video_sync()) {
249 waiting_for_sync_offset
= true;
252 transport_sub_state
= ((!config
.get_external_sync()&& config
.get_auto_return()) ? AutoReturning
: 0);
256 Session::butler_transport_work ()
260 PostTransportWork ptw
;
261 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
263 int on_entry
= g_atomic_int_get (&_butler
->should_do_transport_work
);
265 ptw
= post_transport_work();
267 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw
)));
269 if (ptw
& PostTransportAdjustPlaybackBuffering
) {
270 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
271 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
273 tr
->adjust_playback_buffering ();
274 /* and refill those buffers ... */
275 tr
->non_realtime_locate (_transport_frame
);
281 if (ptw
& PostTransportAdjustCaptureBuffering
) {
282 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
283 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
285 tr
->adjust_capture_buffering ();
290 if (ptw
& PostTransportCurveRealloc
) {
291 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
292 (*i
)->curve_reallocate();
296 if (ptw
& PostTransportInputChange
) {
297 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
298 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
300 tr
->non_realtime_input_change ();
305 if (ptw
& PostTransportSpeed
) {
306 non_realtime_set_speed ();
309 if (ptw
& PostTransportReverse
) {
312 cumulative_rf_motion
= 0;
315 /* don't seek if locate will take care of that in non_realtime_stop() */
317 if (!(ptw
& PostTransportLocate
)) {
319 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
320 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
321 if (tr
&& !tr
->hidden()) {
322 tr
->non_realtime_locate (_transport_frame
);
324 if (on_entry
!= g_atomic_int_get (&_butler
->should_do_transport_work
)) {
325 /* new request, stop seeking, and start again */
326 g_atomic_int_dec_and_test (&_butler
->should_do_transport_work
);
333 if (ptw
& PostTransportLocate
) {
334 non_realtime_locate ();
337 if (ptw
& PostTransportStop
) {
338 non_realtime_stop (ptw
& PostTransportAbort
, on_entry
, finished
);
340 g_atomic_int_dec_and_test (&_butler
->should_do_transport_work
);
345 if (ptw
& PostTransportOverWrite
) {
346 non_realtime_overwrite (on_entry
, finished
);
348 g_atomic_int_dec_and_test (&_butler
->should_do_transport_work
);
353 if (ptw
& PostTransportAudition
) {
354 non_realtime_set_audition ();
357 g_atomic_int_dec_and_test (&_butler
->should_do_transport_work
);
359 DEBUG_TRACE (DEBUG::Transport
, X_("Butler transport work all done\n"));
363 Session::non_realtime_set_speed ()
365 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
366 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
367 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
369 tr
->non_realtime_set_speed ();
375 Session::non_realtime_overwrite (int on_entry
, bool& finished
)
377 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
378 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
379 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
380 if (tr
&& tr
->pending_overwrite ()) {
381 tr
->overwrite_existing_buffers ();
383 if (on_entry
!= g_atomic_int_get (&_butler
->should_do_transport_work
)) {
392 Session::non_realtime_locate ()
394 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
395 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
396 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
398 tr
->non_realtime_locate (_transport_frame
);
405 Session::non_realtime_stop (bool abort
, int on_entry
, bool& finished
)
411 PostTransportWork ptw
= post_transport_work();
416 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
417 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
418 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
419 if (tr
&& tr
->get_captured_frames () != 0) {
425 /* stop and locate are merged here because they share a lot of common stuff */
428 now
= localtime (&xnow
);
431 auditioner
->cancel_audition ();
435 cumulative_rf_motion
= 0;
439 begin_reversible_command ("capture");
440 _have_captured
= true;
443 DEBUG_TRACE (DEBUG::Transport
, X_("Butler PTW: DS stop\n"));
444 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
445 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
447 tr
->transport_stopped_wallclock (*now
, xnow
, abort
);
451 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
453 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
454 if (!(*i
)->is_hidden()) {
455 (*i
)->set_pending_declick (0);
460 commit_reversible_command ();
463 if (_engine
.running()) {
464 update_latency_compensation (true, abort
);
467 bool const auto_return_enabled
=
468 (!config
.get_external_sync() && config
.get_auto_return());
470 if (auto_return_enabled
||
471 (ptw
& PostTransportLocate
) ||
472 (_requested_return_frame
>= 0) ||
475 if (pending_locate_flush
) {
476 flush_all_inserts ();
479 if ((auto_return_enabled
|| synced_to_jack() || _requested_return_frame
>= 0) &&
480 !(ptw
& PostTransportLocate
)) {
482 /* no explicit locate queued */
484 bool do_locate
= false;
486 if (_requested_return_frame
>= 0) {
488 /* explicit return request pre-queued in event list. overrides everything else */
490 cerr
<< "explicit auto-return to " << _requested_return_frame
<< endl
;
492 _transport_frame
= _requested_return_frame
;
496 if (config
.get_auto_return()) {
500 /* don't try to handle loop play when synced to JACK */
502 if (!synced_to_jack()) {
504 Location
*location
= _locations
.auto_loop_location();
507 _transport_frame
= location
->start();
509 _transport_frame
= _last_roll_location
;
514 } else if (_play_range
) {
516 /* return to start of range */
518 if (!current_audio_range
.empty()) {
519 _transport_frame
= current_audio_range
.front().start
;
525 /* regular auto-return */
527 _transport_frame
= _last_roll_location
;
533 _requested_return_frame
= -1;
536 _engine
.transport_locate (_transport_frame
);
542 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
545 if (ptw
& PostTransportClearSubstate
) {
550 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
552 DEBUG_TRACE (DEBUG::Transport
, X_("Butler PTW: locate\n"));
553 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
554 DEBUG_TRACE (DEBUG::Transport
, string_compose ("Butler PTW: locate on %1\n", (*i
)->name()));
555 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
556 if (tr
&& !tr
->hidden()) {
557 tr
->non_realtime_locate (_transport_frame
);
560 if (on_entry
!= g_atomic_int_get (&_butler
->should_do_transport_work
)) {
562 /* we will be back */
569 send_full_time_code (0);
571 if ((ptw
& PostTransportLocate
) && get_record_enabled()) {
572 /* capture start has been changed, so save pending state */
573 save_state ("", true);
577 /* always try to get rid of this */
579 remove_pending_capture_state ();
581 /* save the current state of things if appropriate */
583 if (did_record
&& !saved
) {
584 save_state (_current_snapshot_name
);
587 if (ptw
& PostTransportStop
) {
592 // can't cast away volatile so copy and emit that
593 nframes64_t tframe
= _transport_frame
;
594 PositionChanged (tframe
); /* EMIT SIGNAL */
595 TransportStateChange (); /* EMIT SIGNAL */
597 /* and start it up again if relevant */
599 if ((ptw
& PostTransportLocate
) && !config
.get_external_sync() && pending_locate_roll
) {
600 request_transport_speed (1.0);
601 pending_locate_roll
= false;
606 Session::check_declick_out ()
608 bool locate_required
= transport_sub_state
& PendingLocate
;
610 /* this is called after a process() iteration. if PendingDeclickOut was set,
611 it means that we were waiting to declick the output (which has just been
612 done) before doing something else. this is where we do that "something else".
614 note: called from the audio thread.
617 if (transport_sub_state
& PendingDeclickOut
) {
619 if (locate_required
) {
620 start_locate (pending_locate_frame
, pending_locate_roll
, pending_locate_flush
);
621 transport_sub_state
&= ~(PendingDeclickOut
|PendingLocate
);
623 stop_transport (pending_abort
);
624 transport_sub_state
&= ~(PendingDeclickOut
|PendingLocate
);
630 Session::unset_play_loop ()
633 clear_events (SessionEvent::AutoLoop
);
635 // set all tracks to NOT use internal looping
636 boost::shared_ptr
<RouteList
> rl
= routes
.reader ();
637 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
638 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
639 if (tr
&& !tr
->hidden()) {
646 Session::set_play_loop (bool yn
)
648 /* Called from event-handling context */
652 if (yn
== play_loop
|| (actively_recording() && yn
) || (loc
= _locations
.auto_loop_location()) == 0) {
653 /* nothing to do, or can't change loop status while recording */
659 if (yn
&& Config
->get_seamless_loop() && synced_to_jack()) {
660 warning
<< string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
661 "Recommend changing the configured options"), PROGRAM_NAME
)
674 if (Config
->get_seamless_loop()) {
675 // set all tracks to use internal looping
676 boost::shared_ptr
<RouteList
> rl
= routes
.reader ();
677 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
678 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
679 if (tr
&& !tr
->hidden()) {
685 // set all tracks to NOT use internal looping
686 boost::shared_ptr
<RouteList
> rl
= routes
.reader ();
687 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
688 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
689 if (tr
&& !tr
->hidden()) {
695 /* put the loop event into the event list */
697 SessionEvent
* event
= new SessionEvent (SessionEvent::AutoLoop
, SessionEvent::Replace
, loc
->end(), loc
->start(), 0.0f
);
700 /* locate to start of loop and roll. If doing seamless loop, force a
701 locate+buffer refill even if we are positioned there already.
704 start_locate (loc
->start(), true, true, false, Config
->get_seamless_loop());
712 TransportStateChange ();
715 Session::flush_all_inserts ()
717 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
719 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
720 (*i
)->flush_processors ();
725 Session::start_locate (nframes64_t target_frame
, bool with_roll
, bool with_flush
, bool with_loop
, bool force
)
727 if (synced_to_jack()) {
732 _slave
->speed_and_position (sp
, pos
);
734 if (target_frame
!= pos
) {
736 /* tell JACK to change transport position, and we will
737 follow along later in ::follow_slave()
740 _engine
.transport_locate (target_frame
);
742 if (sp
!= 1.0f
&& with_roll
) {
743 _engine
.transport_start ();
749 locate (target_frame
, with_roll
, with_flush
, with_loop
, force
);
754 Session::micro_locate (nframes_t distance
)
756 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
757 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
758 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
759 if (tr
&& !tr
->can_internal_playback_seek (distance
)) {
764 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
765 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
767 tr
->internal_playback_seek (distance
);
771 _transport_frame
+= distance
;
775 /** @param with_mmc true to send a MMC locate command when the locate is done */
777 Session::locate (nframes64_t target_frame
, bool with_roll
, bool with_flush
, bool with_loop
, bool force
, bool with_mmc
)
779 if (actively_recording() && !with_loop
) {
783 if (!force
&& _transport_frame
== target_frame
&& !loop_changing
&& !with_loop
) {
785 set_transport_speed (1.0, false);
787 loop_changing
= false;
791 // Update Timecode time
792 // [DR] FIXME: find out exactly where this should go below
793 _transport_frame
= target_frame
;
794 timecode_time(_transport_frame
, transmitting_timecode_time
);
795 outbound_mtc_timecode_frame
= _transport_frame
;
796 next_quarter_frame_to_send
= 0;
798 if (_transport_speed
&& (!with_loop
|| loop_changing
)) {
799 /* schedule a declick. we'll be called again when its done */
801 if (!(transport_sub_state
& PendingDeclickOut
)) {
802 transport_sub_state
|= (PendingDeclickOut
|PendingLocate
);
803 pending_locate_frame
= target_frame
;
804 pending_locate_roll
= with_roll
;
805 pending_locate_flush
= with_flush
;
810 if (transport_rolling() && (!auto_play_legal
|| !config
.get_auto_play()) && !with_roll
&& !(synced_to_jack() && play_loop
)) {
811 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
814 if (force
|| !with_loop
|| loop_changing
) {
816 PostTransportWork todo
= PostTransportLocate
;
819 todo
= PostTransportWork (todo
| PostTransportRoll
);
822 add_post_transport_work (todo
);
823 _butler
->schedule_transport_work ();
827 /* this is functionally what clear_clicks() does but with a tentative lock */
829 Glib::RWLock::WriterLock
clickm (click_lock
, Glib::TRY_LOCK
);
831 if (clickm
.locked()) {
833 for (Clicks::iterator i
= clicks
.begin(); i
!= clicks
.end(); ++i
) {
842 /* switch from input if we're going to roll */
843 if (Config
->get_monitoring_model() == HardwareMonitoring
) {
845 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
846 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
847 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
848 if (tr
&& tr
->record_enabled ()) {
849 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
850 tr
->monitor_input (!config
.get_auto_input());
855 /* otherwise we're going to stop, so do the opposite */
856 if (Config
->get_monitoring_model() == HardwareMonitoring
) {
858 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
859 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
860 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
861 if (tr
&& tr
->record_enabled ()) {
862 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
863 tr
->monitor_input (true);
869 /* cancel looped playback if transport pos outside of loop range */
871 Location
* al
= _locations
.auto_loop_location();
873 if (al
&& (_transport_frame
< al
->start() || _transport_frame
> al
->end())) {
874 // cancel looping directly, this is called from event handling context
875 set_play_loop (false);
877 else if (al
&& _transport_frame
== al
->start()) {
879 // this is only necessary for seamless looping
881 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
882 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
883 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
884 if (tr
&& tr
->record_enabled ()) {
885 // tell it we've looped, so it can deal with the record state
886 tr
->transport_looped(_transport_frame
);
891 TransportLooped(); // EMIT SIGNAL
895 loop_changing
= false;
897 _send_timecode_update
= true;
899 if (with_mmc
&& _mmc
) {
901 timecode_time_subframes (_transport_frame
, time
);
902 _mmc
->send (MIDI::MachineControlCommand (time
));
905 Located (); /* EMIT SIGNAL */
908 /** Set the transport speed.
909 * @param speed New speed
913 Session::set_transport_speed (double speed
, bool abort
, bool clear_state
)
915 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
));
917 if (_transport_speed
== speed
) {
921 _target_transport_speed
= fabs(speed
);
923 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
924 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
928 speed
= min (8.0, speed
);
929 } else if (speed
< 0) {
930 speed
= max (-8.0, speed
);
933 if (transport_rolling() && speed
== 0.0) {
935 /* we are rolling and we want to stop */
937 if (Config
->get_monitoring_model() == HardwareMonitoring
)
939 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
940 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
941 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
942 if (tr
&& tr
->record_enabled ()) {
943 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
944 tr
->monitor_input (true);
949 if (synced_to_jack ()) {
951 /* do this here because our response to the slave won't
957 _engine
.transport_stop ();
959 stop_transport (abort
);
962 } else if (transport_stopped() && speed
== 1.0) {
964 /* we are stopped and we want to start rolling at speed 1 */
966 if (Config
->get_monitoring_model() == HardwareMonitoring
) {
968 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
969 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
970 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
971 if (config
.get_auto_input() && tr
&& tr
->record_enabled ()) {
972 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
973 tr
->monitor_input (false);
978 if (synced_to_jack()) {
979 _engine
.transport_start ();
986 if ((synced_to_jack()) && speed
!= 0.0 && speed
!= 1.0) {
987 warning
<< string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
993 if (actively_recording()) {
997 if (speed
> 0.0 && _transport_frame
== current_end_frame()) {
1001 if (speed
< 0.0 && _transport_frame
== 0) {
1007 /* if we are reversing relative to the current speed, or relative to the speed
1008 before the last stop, then we have to do extra work.
1011 PostTransportWork todo
= PostTransportWork (0);
1013 if ((_transport_speed
&& speed
* _transport_speed
< 0.0) || (_last_transport_speed
* speed
< 0.0) || (_last_transport_speed
== 0.0f
&& speed
< 0.0f
)) {
1014 todo
= PostTransportWork (todo
| PostTransportReverse
);
1015 _last_roll_or_reversal_location
= _transport_frame
;
1018 _last_transport_speed
= _transport_speed
;
1019 _transport_speed
= speed
;
1021 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
1022 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
1023 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
1024 if (tr
&& tr
->realtime_set_speed (tr
->speed(), true)) {
1025 todo
= PostTransportWork (todo
| PostTransportSpeed
);
1031 add_post_transport_work (todo
);
1032 _butler
->schedule_transport_work ();
1038 /** Stop the transport. */
1040 Session::stop_transport (bool abort
, bool clear_state
)
1042 if (_transport_speed
== 0.0f
) {
1046 if (actively_recording() && !(transport_sub_state
& StopPendingCapture
) && _worst_output_latency
> current_block_size
) {
1048 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
1049 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
1050 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
1052 tr
->prepare_to_stop (_transport_frame
);
1056 /* we need to capture the audio that has still not yet been received by the system
1057 at the time the stop is requested, so we have to roll past that time.
1059 we want to declick before stopping, so schedule the autostop for one
1060 block before the actual end. we'll declick in the subsequent block,
1061 and then we'll really be stopped.
1064 SessionEvent
*ev
= new SessionEvent (SessionEvent::StopOnce
, SessionEvent::Replace
,
1065 _transport_frame
+ _worst_output_latency
- current_block_size
,
1069 transport_sub_state
|= StopPendingCapture
;
1070 pending_abort
= abort
;
1075 if ((transport_sub_state
& PendingDeclickOut
) == 0) {
1077 if (!(transport_sub_state
& StopPendingCapture
)) {
1078 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
1079 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
1080 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
1082 tr
->prepare_to_stop (_transport_frame
);
1087 transport_sub_state
|= PendingDeclickOut
;
1088 /* we'll be called again after the declick */
1089 pending_abort
= abort
;
1093 realtime_stop (abort
, clear_state
);
1094 _butler
->schedule_transport_work ();
1098 Session::start_transport ()
1100 _last_roll_location
= _transport_frame
;
1101 _last_roll_or_reversal_location
= _transport_frame
;
1103 have_looped
= false;
1105 /* if record status is Enabled, move it to Recording. if its
1106 already Recording, move it to Disabled.
1109 switch (record_status()) {
1111 if (!config
.get_punch_in()) {
1118 disable_record (false);
1126 transport_sub_state
|= PendingDeclickIn
;
1128 _transport_speed
= 1.0;
1129 _target_transport_speed
= 1.0;
1131 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
1132 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
1133 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
1135 tr
->realtime_set_speed (tr
->speed(), true);
1140 Timecode::Time time
;
1141 timecode_time_subframes (_transport_frame
, time
);
1142 _mmc
->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay
));
1145 TransportStateChange (); /* EMIT SIGNAL */
1148 /** Do any transport work in the audio thread that needs to be done after the
1149 * transport thread is finished. Audio thread, realtime safe.
1152 Session::post_transport ()
1154 PostTransportWork ptw
= post_transport_work ();
1156 if (ptw
& PostTransportAudition
) {
1157 if (auditioner
&& auditioner
->auditioning()) {
1158 process_function
= &Session::process_audition
;
1160 process_function
= &Session::process_with_events
;
1164 if (ptw
& PostTransportStop
) {
1166 transport_sub_state
= 0;
1169 if (ptw
& PostTransportLocate
) {
1171 if (((!config
.get_external_sync() && (auto_play_legal
&& config
.get_auto_play())) && !_exporting
) || (ptw
& PostTransportRoll
)) {
1175 transport_sub_state
= 0;
1180 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1183 set_post_transport_work (PostTransportWork (0));
1187 Session::reset_rf_scale (nframes_t motion
)
1189 cumulative_rf_motion
+= motion
;
1191 if (cumulative_rf_motion
< 4 * _current_frame_rate
) {
1193 } else if (cumulative_rf_motion
< 8 * _current_frame_rate
) {
1195 } else if (cumulative_rf_motion
< 16 * _current_frame_rate
) {
1207 Session::use_sync_source (Slave
* new_slave
)
1209 /* Runs in process() context */
1211 bool non_rt_required
= false;
1213 /* XXX this deletion is problematic because we're in RT context */
1218 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
1219 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
1220 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
1221 if (tr
&& !tr
->hidden()) {
1222 if (tr
->realtime_set_speed (tr
->speed(), true)) {
1223 non_rt_required
= true;
1225 tr
->set_slaved (_slave
!= 0);
1229 if (non_rt_required
) {
1230 add_post_transport_work (PostTransportSpeed
);
1231 _butler
->schedule_transport_work ();
1238 Session::drop_sync_source ()
1240 request_sync_source (0);
1244 Session::switch_to_sync_source (SyncSource src
)
1248 DEBUG_TRACE (DEBUG::Slave
, string_compose ("Setting up sync source %1\n", enum_2_string (src
)));
1252 if (_slave
&& dynamic_cast<MTC_Slave
*>(_slave
)) {
1258 new_slave
= new MTC_Slave (*this, *_mtc_port
);
1261 catch (failed_constructor
& err
) {
1266 error
<< _("No MTC port defined: MTC slaving is impossible.") << endmsg
;
1272 if (_slave
&& dynamic_cast<MIDIClock_Slave
*>(_slave
)) {
1276 if (_midi_clock_port
) {
1278 new_slave
= new MIDIClock_Slave (*this, *_midi_clock_port
, 24);
1281 catch (failed_constructor
& err
) {
1286 error
<< _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg
;
1292 if (_slave
&& dynamic_cast<JACK_Slave
*>(_slave
)) {
1296 new_slave
= new JACK_Slave (_engine
.jack());
1304 request_sync_source (new_slave
);
1308 Session::reverse_track_buffers ()
1310 add_post_transport_work (PostTransportReverse
);
1311 _butler
->schedule_transport_work ();
1315 Session::set_track_speed (Track
* track
, double speed
)
1317 if (track
->realtime_set_speed (speed
, false)) {
1318 add_post_transport_work (PostTransportSpeed
);
1319 _butler
->schedule_transport_work ();
1325 Session::unset_play_range ()
1327 _play_range
= false;
1328 _clear_event_type (SessionEvent::RangeStop
);
1329 _clear_event_type (SessionEvent::RangeLocate
);
1333 Session::set_play_range (list
<AudioRange
>& range
, bool leave_rolling
)
1337 /* Called from event-processing context */
1339 unset_play_range ();
1341 if (range
.empty()) {
1342 /* _play_range set to false in unset_play_range()
1344 if (!leave_rolling
) {
1345 /* stop transport */
1346 SessionEvent
* ev
= new SessionEvent (SessionEvent::SetTransportSpeed
, SessionEvent::Add
, SessionEvent::Immediate
, 0, 0.0f
, false);
1354 /* cancel loop play */
1357 list
<AudioRange
>::size_type sz
= range
.size();
1361 list
<AudioRange
>::iterator i
= range
.begin();
1362 list
<AudioRange
>::iterator next
;
1364 while (i
!= range
.end()) {
1369 /* locating/stopping is subject to delays for declicking.
1372 nframes_t requested_frame
= (*i
).end
;
1374 if (requested_frame
> current_block_size
) {
1375 requested_frame
-= current_block_size
;
1377 requested_frame
= 0;
1380 if (next
== range
.end()) {
1381 ev
= new SessionEvent (SessionEvent::RangeStop
, SessionEvent::Add
, requested_frame
, 0, 0.0f
);
1383 ev
= new SessionEvent (SessionEvent::RangeLocate
, SessionEvent::Add
, requested_frame
, (*next
).start
, 0.0f
);
1391 } else if (sz
== 1) {
1393 ev
= new SessionEvent (SessionEvent::RangeStop
, SessionEvent::Add
, range
.front().end
, 0, 0.0f
);
1398 /* save range so we can do auto-return etc. */
1400 current_audio_range
= range
;
1402 /* now start rolling at the right place */
1404 ev
= new SessionEvent (SessionEvent::LocateRoll
, SessionEvent::Add
, SessionEvent::Immediate
, range
.front().start
, 0.0f
, false);
1407 TransportStateChange ();
1411 Session::request_bounded_roll (nframes_t start
, nframes_t end
)
1413 AudioRange
ar (start
, end
, 0);
1414 list
<AudioRange
> lar
;
1417 request_play_range (&lar
, true);
1420 Session::request_roll_at_and_return (nframes_t start
, nframes_t return_to
)
1422 SessionEvent
*ev
= new SessionEvent (SessionEvent::LocateRollLocate
, SessionEvent::Add
, SessionEvent::Immediate
, return_to
, 1.0);
1423 ev
->target2_frame
= start
;
1428 Session::engine_halted ()
1432 /* there will be no more calls to process(), so
1433 we'd better clean up for ourselves, right now.
1435 but first, make sure the butler is out of
1439 g_atomic_int_set (&_butler
->should_do_transport_work
, 0);
1440 set_post_transport_work (PostTransportWork (0));
1443 realtime_stop (false, true);
1444 non_realtime_stop (false, 0, ignored
);
1445 transport_sub_state
= 0;
1447 TransportStateChange (); /* EMIT SIGNAL */
1452 Session::xrun_recovery ()
1454 // can't cast away volatile so copy and emit that
1455 nframes64_t tframe
= _transport_frame
;
1456 Xrun (tframe
); //EMIT SIGNAL
1458 if (Config
->get_stop_recording_on_xrun() && actively_recording()) {
1460 /* it didn't actually halt, but we need
1461 to handle things in the same way.
1469 Session::route_processors_changed (RouteProcessorChange c
)
1471 if (c
.type
== RouteProcessorChange::MeterPointChange
) {
1475 update_latency_compensation (false, false);
1480 Session::update_latency_compensation (bool with_stop
, bool abort
)
1482 bool update_jack
= false;
1483 PostTransportWork ptw
;
1485 if (_state_of_the_state
& Deletion
) {
1489 _worst_track_latency
= 0;
1490 ptw
= post_transport_work();
1492 #undef DEBUG_LATENCY
1493 #ifdef DEBUG_LATENCY
1494 cerr
<< "\n---------------------------------\nUPDATE LATENCY\n";
1497 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
1499 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
1502 (*i
)->handle_transport_stopped (abort
, (ptw
& PostTransportLocate
), (!(ptw
& PostTransportLocate
) || pending_locate_flush
));
1505 nframes_t old_latency
= (*i
)->output()->signal_latency ();
1506 nframes_t track_latency
= (*i
)->update_total_latency ();
1508 if (old_latency
!= track_latency
) {
1509 (*i
)->input()->update_port_total_latencies ();
1510 (*i
)->output()->update_port_total_latencies ();
1514 if (!(*i
)->is_hidden() && ((*i
)->active())) {
1515 _worst_track_latency
= max (_worst_track_latency
, track_latency
);
1520 _engine
.update_total_latencies ();
1523 #ifdef DEBUG_LATENCY
1524 cerr
<< "\tworst was " << _worst_track_latency
<< endl
;
1527 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
1528 (*i
)->set_latency_delay (_worst_track_latency
);
1531 set_worst_io_latencies ();
1533 /* reflect any changes in latencies into capture offsets
1536 boost::shared_ptr
<RouteList
> rl
= routes
.reader();
1537 for (RouteList::iterator i
= rl
->begin(); i
!= rl
->end(); ++i
) {
1538 boost::shared_ptr
<Track
> tr
= boost::dynamic_pointer_cast
<Track
> (*i
);
1540 tr
->set_capture_offset ();
1546 Session::allow_auto_play (bool yn
)
1548 auto_play_legal
= yn
;
1552 Session::reset_jack_connection (jack_client_t
* jack
)
1556 if (_slave
&& ((js
= dynamic_cast<JACK_Slave
*> (_slave
)) != 0)) {
1557 js
->reset_client (jack
);
1562 Session::maybe_stop (nframes_t limit
)
1564 if ((_transport_speed
> 0.0f
&& _transport_frame
>= limit
) || (_transport_speed
< 0.0f
&& _transport_frame
== 0)) {
1565 if (synced_to_jack () && config
.get_jack_time_master ()) {
1566 _engine
.transport_stop ();
1567 } else if (!synced_to_jack ()) {