Setup fixed ports for MIDI control data; hence remove configuration of those ports...
[ArdourMidi.git] / libs / ardour / session_transport.cc
blob1123a6038b8388f4bf63a741f02eb0dbdd46527f
1 /*
2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <cmath>
21 #include <cerrno>
22 #include <unistd.h>
25 #include "pbd/undo.h"
26 #include "pbd/error.h"
27 #include "pbd/enumwriter.h"
28 #include "pbd/pthread_utils.h"
29 #include "pbd/memento_command.h"
31 #include "midi++/mmc.h"
32 #include "midi++/port.h"
34 #include "ardour/ardour.h"
35 #include "ardour/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"
43 #include "i18n.h"
45 using namespace std;
46 using namespace ARDOUR;
47 using namespace PBD;
49 void
50 Session::add_post_transport_work (PostTransportWork ptw)
52 PostTransportWork oldval;
53 PostTransportWork newval;
54 int tries = 0;
56 while (tries < 8) {
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)) {
60 /* success */
61 return;
65 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
68 void
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);
73 queue_event (ev);
77 void
78 Session::request_sync_source (Slave* new_slave)
80 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
81 bool seamless;
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);
88 } else {
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;
97 queue_event (ev);
100 void
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));
105 queue_event (ev);
108 void
109 Session::request_track_speed (Track* tr, double speed)
111 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
112 ev->set_ptr (tr);
113 queue_event (ev);
116 void
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));
121 queue_event (ev);
124 void
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));
129 queue_event (ev);
132 void
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));
137 queue_event (ev);
140 void
141 Session::request_play_loop (bool yn, bool leave_rolling)
143 SessionEvent* ev;
144 Location *location = _locations.auto_loop_location();
146 if (location == 0 && yn) {
147 error << _("Cannot loop - no loop range defined")
148 << endmsg;
149 return;
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));
154 queue_event (ev);
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);
163 void
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));
167 if (range) {
168 ev->audio_range = *range;
169 } else {
170 ev->audio_range.clear ();
172 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
173 queue_event (ev);
176 void
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();
187 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
188 send_mmc_locate (_transport_frame);
190 if (_transport_speed < 0.0f) {
191 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
192 } else {
193 todo = PostTransportWork (todo | PostTransportStop);
196 if (actively_recording()) {
198 /* move the transport position back to where the
199 request for a stop was noticed. we rolled
200 past that point to pick up delayed input (and/or to delick)
203 if (_worst_output_latency > current_block_size) {
204 /* we rolled past the stop point to pick up data that had
205 not yet arrived. move back to where the stop occured.
207 decrement_transport_position (current_block_size + (_worst_output_latency - current_block_size));
208 } else {
209 decrement_transport_position (current_block_size);
212 /* the duration change is not guaranteed to have happened, but is likely */
214 todo = PostTransportWork (todo | PostTransportDuration);
217 if (abort) {
218 todo = PostTransportWork (todo | PostTransportAbort);
221 if (clear_state) {
222 todo = PostTransportWork (todo | PostTransportClearSubstate);
225 if (todo) {
226 add_post_transport_work (todo);
229 _clear_event_type (SessionEvent::StopOnce);
230 _clear_event_type (SessionEvent::RangeStop);
231 _clear_event_type (SessionEvent::RangeLocate);
233 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
234 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
236 reset_slave_state ();
238 _transport_speed = 0;
239 _target_transport_speed = 0;
241 g_atomic_int_set (&_playback_load, 100);
242 g_atomic_int_set (&_capture_load, 100);
244 if (config.get_use_video_sync()) {
245 waiting_for_sync_offset = true;
248 transport_sub_state = ((!config.get_external_sync()&& config.get_auto_return()) ? AutoReturning : 0);
251 void
252 Session::butler_transport_work ()
254 restart:
255 bool finished;
256 PostTransportWork ptw;
257 boost::shared_ptr<RouteList> r = routes.reader ();
259 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
260 finished = true;
261 ptw = post_transport_work();
263 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
265 if (ptw & PostTransportAdjustPlaybackBuffering) {
266 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
267 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
268 if (tr) {
269 tr->adjust_playback_buffering ();
270 /* and refill those buffers ... */
271 tr->non_realtime_locate (_transport_frame);
277 if (ptw & PostTransportAdjustCaptureBuffering) {
278 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
279 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
280 if (tr) {
281 tr->adjust_capture_buffering ();
286 if (ptw & PostTransportCurveRealloc) {
287 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
288 (*i)->curve_reallocate();
292 if (ptw & PostTransportInputChange) {
293 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
294 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
295 if (tr) {
296 tr->non_realtime_input_change ();
301 if (ptw & PostTransportSpeed) {
302 non_realtime_set_speed ();
305 if (ptw & PostTransportReverse) {
307 clear_clicks();
308 cumulative_rf_motion = 0;
309 reset_rf_scale (0);
311 /* don't seek if locate will take care of that in non_realtime_stop() */
313 if (!(ptw & PostTransportLocate)) {
315 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
316 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
317 if (tr && !tr->hidden()) {
318 tr->non_realtime_locate (_transport_frame);
320 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
321 /* new request, stop seeking, and start again */
322 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
323 goto restart;
329 if (ptw & PostTransportLocate) {
330 non_realtime_locate ();
333 if (ptw & PostTransportStop) {
334 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
335 if (!finished) {
336 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
337 goto restart;
341 if (ptw & PostTransportOverWrite) {
342 non_realtime_overwrite (on_entry, finished);
343 if (!finished) {
344 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
345 goto restart;
349 if (ptw & PostTransportAudition) {
350 non_realtime_set_audition ();
353 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
355 DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
358 void
359 Session::non_realtime_set_speed ()
361 boost::shared_ptr<RouteList> rl = routes.reader();
362 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
363 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
364 if (tr) {
365 tr->non_realtime_set_speed ();
370 void
371 Session::non_realtime_overwrite (int on_entry, bool& finished)
373 boost::shared_ptr<RouteList> rl = routes.reader();
374 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
375 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
376 if (tr && tr->pending_overwrite ()) {
377 tr->overwrite_existing_buffers ();
379 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
380 finished = false;
381 return;
387 void
388 Session::non_realtime_locate ()
390 boost::shared_ptr<RouteList> rl = routes.reader();
391 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
392 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
393 if (tr) {
394 tr->non_realtime_locate (_transport_frame);
400 void
401 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
403 struct tm* now;
404 time_t xnow;
405 bool did_record;
406 bool saved;
407 PostTransportWork ptw = post_transport_work();
409 did_record = false;
410 saved = false;
412 boost::shared_ptr<RouteList> rl = routes.reader();
413 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
414 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
415 if (tr && tr->get_captured_frames () != 0) {
416 did_record = true;
417 break;
421 /* stop and locate are merged here because they share a lot of common stuff */
423 time (&xnow);
424 now = localtime (&xnow);
426 if (auditioner) {
427 auditioner->cancel_audition ();
430 clear_clicks();
431 cumulative_rf_motion = 0;
432 reset_rf_scale (0);
434 if (did_record) {
435 begin_reversible_command ("capture");
436 _have_captured = true;
439 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
440 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
441 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
442 if (tr) {
443 tr->transport_stopped_wallclock (*now, xnow, abort);
447 boost::shared_ptr<RouteList> r = routes.reader ();
449 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
450 if (!(*i)->is_hidden()) {
451 (*i)->set_pending_declick (0);
455 if (did_record) {
456 commit_reversible_command ();
459 if (_engine.running()) {
460 update_latency_compensation (true, abort);
463 bool const auto_return_enabled =
464 (!config.get_external_sync() && config.get_auto_return());
466 if (auto_return_enabled ||
467 (ptw & PostTransportLocate) ||
468 (_requested_return_frame >= 0) ||
469 synced_to_jack()) {
471 if (pending_locate_flush) {
472 flush_all_inserts ();
475 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
476 !(ptw & PostTransportLocate)) {
478 /* no explicit locate queued */
480 bool do_locate = false;
482 if (_requested_return_frame >= 0) {
484 /* explicit return request pre-queued in event list. overrides everything else */
486 cerr << "explicit auto-return to " << _requested_return_frame << endl;
488 _transport_frame = _requested_return_frame;
489 do_locate = true;
491 } else {
492 if (config.get_auto_return()) {
494 if (play_loop) {
496 /* don't try to handle loop play when synced to JACK */
498 if (!synced_to_jack()) {
500 Location *location = _locations.auto_loop_location();
502 if (location != 0) {
503 _transport_frame = location->start();
504 } else {
505 _transport_frame = _last_roll_location;
507 do_locate = true;
510 } else if (_play_range) {
512 /* return to start of range */
514 if (!current_audio_range.empty()) {
515 _transport_frame = current_audio_range.front().start;
516 do_locate = true;
519 } else {
521 /* regular auto-return */
523 _transport_frame = _last_roll_location;
524 do_locate = true;
529 _requested_return_frame = -1;
531 if (do_locate) {
532 _engine.transport_locate (_transport_frame);
538 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
541 if (ptw & PostTransportClearSubstate) {
542 _play_range = false;
543 unset_play_loop ();
546 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
548 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
549 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
550 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
551 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
552 if (tr && !tr->hidden()) {
553 tr->non_realtime_locate (_transport_frame);
556 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
557 finished = false;
558 /* we will be back */
559 return;
563 have_looped = false;
565 send_full_time_code (0);
567 if ((ptw & PostTransportLocate) && get_record_enabled()) {
568 /* capture start has been changed, so save pending state */
569 save_state ("", true);
570 saved = true;
573 /* always try to get rid of this */
575 remove_pending_capture_state ();
577 /* save the current state of things if appropriate */
579 if (did_record && !saved) {
580 save_state (_current_snapshot_name);
583 if (ptw & PostTransportStop) {
584 _play_range = false;
585 play_loop = false;
588 // can't cast away volatile so copy and emit that
589 nframes64_t tframe = _transport_frame;
590 PositionChanged (tframe); /* EMIT SIGNAL */
591 TransportStateChange (); /* EMIT SIGNAL */
593 /* and start it up again if relevant */
595 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
596 request_transport_speed (1.0);
597 pending_locate_roll = false;
601 void
602 Session::check_declick_out ()
604 bool locate_required = transport_sub_state & PendingLocate;
606 /* this is called after a process() iteration. if PendingDeclickOut was set,
607 it means that we were waiting to declick the output (which has just been
608 done) before doing something else. this is where we do that "something else".
610 note: called from the audio thread.
613 if (transport_sub_state & PendingDeclickOut) {
615 if (locate_required) {
616 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
617 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
618 } else {
619 stop_transport (pending_abort);
620 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
625 void
626 Session::unset_play_loop ()
628 play_loop = false;
629 clear_events (SessionEvent::AutoLoop);
631 // set all tracks to NOT use internal looping
632 boost::shared_ptr<RouteList> rl = routes.reader ();
633 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
634 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
635 if (tr && !tr->hidden()) {
636 tr->set_loop (0);
641 void
642 Session::set_play_loop (bool yn)
644 /* Called from event-handling context */
646 Location *loc;
648 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
649 /* nothing to do, or can't change loop status while recording */
650 return;
653 set_dirty();
655 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
656 warning << string_compose (_("Seamless looping cannot be supported while %1 is using JACK transport.\n"
657 "Recommend changing the configured options"), PROGRAM_NAME)
658 << endmsg;
659 return;
662 if (yn) {
664 play_loop = true;
666 if (loc) {
668 unset_play_range ();
670 if (Config->get_seamless_loop()) {
671 // set all tracks to use internal looping
672 boost::shared_ptr<RouteList> rl = routes.reader ();
673 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
674 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
675 if (tr && !tr->hidden()) {
676 tr->set_loop (loc);
680 else {
681 // set all tracks to NOT use internal looping
682 boost::shared_ptr<RouteList> rl = routes.reader ();
683 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
684 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
685 if (tr && !tr->hidden()) {
686 tr->set_loop (0);
691 /* put the loop event into the event list */
693 SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
694 merge_event (event);
696 /* locate to start of loop and roll. If doing seamless loop, force a
697 locate+buffer refill even if we are positioned there already.
700 start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
703 } else {
705 unset_play_loop ();
708 TransportStateChange ();
710 void
711 Session::flush_all_inserts ()
713 boost::shared_ptr<RouteList> r = routes.reader ();
715 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
716 (*i)->flush_processors ();
720 void
721 Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
723 if (synced_to_jack()) {
725 double sp;
726 nframes64_t pos;
728 _slave->speed_and_position (sp, pos);
730 if (target_frame != pos) {
732 /* tell JACK to change transport position, and we will
733 follow along later in ::follow_slave()
736 _engine.transport_locate (target_frame);
738 if (sp != 1.0f && with_roll) {
739 _engine.transport_start ();
744 } else {
745 locate (target_frame, with_roll, with_flush, with_loop, force);
750 Session::micro_locate (nframes_t distance)
752 boost::shared_ptr<RouteList> rl = routes.reader();
753 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
754 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
755 if (tr && !tr->can_internal_playback_seek (distance)) {
756 return -1;
760 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
761 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
762 if (tr) {
763 tr->internal_playback_seek (distance);
767 _transport_frame += distance;
768 return 0;
771 /** @param with_mmc true to send a MMC locate command when the locate is done */
772 void
773 Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
775 if (actively_recording() && !with_loop) {
776 return;
779 if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
780 if (with_roll) {
781 set_transport_speed (1.0, false);
783 loop_changing = false;
784 Located (); /* EMIT SIGNAL */
785 return;
788 // Update Timecode time
789 // [DR] FIXME: find out exactly where this should go below
790 _transport_frame = target_frame;
791 timecode_time(_transport_frame, transmitting_timecode_time);
792 outbound_mtc_timecode_frame = _transport_frame;
793 next_quarter_frame_to_send = 0;
795 if (_transport_speed && (!with_loop || loop_changing)) {
796 /* schedule a declick. we'll be called again when its done */
798 if (!(transport_sub_state & PendingDeclickOut)) {
799 transport_sub_state |= (PendingDeclickOut|PendingLocate);
800 pending_locate_frame = target_frame;
801 pending_locate_roll = with_roll;
802 pending_locate_flush = with_flush;
803 return;
807 if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
808 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
811 if (force || !with_loop || loop_changing) {
813 PostTransportWork todo = PostTransportLocate;
815 if (with_roll) {
816 todo = PostTransportWork (todo | PostTransportRoll);
819 add_post_transport_work (todo);
820 _butler->schedule_transport_work ();
822 } else {
824 /* this is functionally what clear_clicks() does but with a tentative lock */
826 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
828 if (clickm.locked()) {
830 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
831 delete *i;
834 clicks.clear ();
838 if (with_roll) {
839 /* switch from input if we're going to roll */
840 if (Config->get_monitoring_model() == HardwareMonitoring) {
842 boost::shared_ptr<RouteList> rl = routes.reader();
843 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
844 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
845 if (tr && tr->record_enabled ()) {
846 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
847 tr->monitor_input (!config.get_auto_input());
851 } else {
852 /* otherwise we're going to stop, so do the opposite */
853 if (Config->get_monitoring_model() == HardwareMonitoring) {
855 boost::shared_ptr<RouteList> rl = routes.reader();
856 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
857 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
858 if (tr && tr->record_enabled ()) {
859 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
860 tr->monitor_input (true);
866 /* cancel looped playback if transport pos outside of loop range */
867 if (play_loop) {
868 Location* al = _locations.auto_loop_location();
870 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
871 // cancel looping directly, this is called from event handling context
872 set_play_loop (false);
874 else if (al && _transport_frame == al->start()) {
875 if (with_loop) {
876 // this is only necessary for seamless looping
878 boost::shared_ptr<RouteList> rl = routes.reader();
879 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
880 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
881 if (tr && tr->record_enabled ()) {
882 // tell it we've looped, so it can deal with the record state
883 tr->transport_looped(_transport_frame);
887 have_looped = true;
888 TransportLooped(); // EMIT SIGNAL
892 loop_changing = false;
894 _send_timecode_update = true;
896 if (with_mmc) {
897 send_mmc_locate (_transport_frame);
900 Located (); /* EMIT SIGNAL */
903 /** Set the transport speed.
904 * @param speed New speed
905 * @param abort
907 void
908 Session::set_transport_speed (double speed, bool abort, bool clear_state)
910 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));
912 if (_transport_speed == speed) {
913 return;
916 _target_transport_speed = fabs(speed);
918 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
919 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
922 if (speed > 0) {
923 speed = min (8.0, speed);
924 } else if (speed < 0) {
925 speed = max (-8.0, speed);
928 if (transport_rolling() && speed == 0.0) {
930 /* we are rolling and we want to stop */
932 if (Config->get_monitoring_model() == HardwareMonitoring)
934 boost::shared_ptr<RouteList> rl = routes.reader();
935 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
936 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
937 if (tr && tr->record_enabled ()) {
938 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
939 tr->monitor_input (true);
944 if (synced_to_jack ()) {
945 if (clear_state) {
946 /* do this here because our response to the slave won't
947 take care of it.
949 _play_range = false;
950 unset_play_loop ();
952 _engine.transport_stop ();
953 } else {
954 stop_transport (abort);
957 } else if (transport_stopped() && speed == 1.0) {
959 /* we are stopped and we want to start rolling at speed 1 */
961 if (Config->get_monitoring_model() == HardwareMonitoring) {
963 boost::shared_ptr<RouteList> rl = routes.reader();
964 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
965 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
966 if (config.get_auto_input() && tr && tr->record_enabled ()) {
967 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
968 tr->monitor_input (false);
973 if (synced_to_jack()) {
974 _engine.transport_start ();
975 } else {
976 start_transport ();
979 } else {
981 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
982 warning << string_compose (_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
983 PROGRAM_NAME)
984 << endmsg;
985 return;
988 if (actively_recording()) {
989 return;
992 if (speed > 0.0 && _transport_frame == current_end_frame()) {
993 return;
996 if (speed < 0.0 && _transport_frame == 0) {
997 return;
1000 clear_clicks ();
1002 /* if we are reversing relative to the current speed, or relative to the speed
1003 before the last stop, then we have to do extra work.
1006 PostTransportWork todo = PostTransportWork (0);
1008 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1009 todo = PostTransportWork (todo | PostTransportReverse);
1010 _last_roll_or_reversal_location = _transport_frame;
1013 _last_transport_speed = _transport_speed;
1014 _transport_speed = speed;
1016 boost::shared_ptr<RouteList> rl = routes.reader();
1017 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1018 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1019 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1020 todo = PostTransportWork (todo | PostTransportSpeed);
1021 break;
1025 if (todo) {
1026 add_post_transport_work (todo);
1027 _butler->schedule_transport_work ();
1033 /** Stop the transport. */
1034 void
1035 Session::stop_transport (bool abort, bool clear_state)
1037 if (_transport_speed == 0.0f) {
1038 return;
1041 if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) {
1043 boost::shared_ptr<RouteList> rl = routes.reader();
1044 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1045 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1046 if (tr) {
1047 tr->prepare_to_stop (_transport_frame);
1051 /* we need to capture the audio that has still not yet been received by the system
1052 at the time the stop is requested, so we have to roll past that time.
1054 we want to declick before stopping, so schedule the autostop for one
1055 block before the actual end. we'll declick in the subsequent block,
1056 and then we'll really be stopped.
1059 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1060 _transport_frame + _worst_output_latency - current_block_size,
1061 0, 0, abort);
1063 merge_event (ev);
1064 transport_sub_state |= StopPendingCapture;
1065 pending_abort = abort;
1066 return;
1070 if ((transport_sub_state & PendingDeclickOut) == 0) {
1072 if (!(transport_sub_state & StopPendingCapture)) {
1073 boost::shared_ptr<RouteList> rl = routes.reader();
1074 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1075 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1076 if (tr) {
1077 tr->prepare_to_stop (_transport_frame);
1082 transport_sub_state |= PendingDeclickOut;
1083 /* we'll be called again after the declick */
1084 pending_abort = abort;
1085 return;
1088 realtime_stop (abort, clear_state);
1089 _butler->schedule_transport_work ();
1092 void
1093 Session::start_transport ()
1095 _last_roll_location = _transport_frame;
1096 _last_roll_or_reversal_location = _transport_frame;
1098 have_looped = false;
1100 /* if record status is Enabled, move it to Recording. if its
1101 already Recording, move it to Disabled.
1104 switch (record_status()) {
1105 case Enabled:
1106 if (!config.get_punch_in()) {
1107 enable_record ();
1109 break;
1111 case Recording:
1112 if (!play_loop) {
1113 disable_record (false);
1115 break;
1117 default:
1118 break;
1121 transport_sub_state |= PendingDeclickIn;
1123 _transport_speed = 1.0;
1124 _target_transport_speed = 1.0;
1126 boost::shared_ptr<RouteList> rl = routes.reader();
1127 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1128 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1129 if (tr) {
1130 tr->realtime_set_speed (tr->speed(), true);
1134 Timecode::Time time;
1135 timecode_time_subframes (_transport_frame, time);
1136 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1138 TransportStateChange (); /* EMIT SIGNAL */
1141 /** Do any transport work in the audio thread that needs to be done after the
1142 * transport thread is finished. Audio thread, realtime safe.
1144 void
1145 Session::post_transport ()
1147 PostTransportWork ptw = post_transport_work ();
1149 if (ptw & PostTransportAudition) {
1150 if (auditioner && auditioner->auditioning()) {
1151 process_function = &Session::process_audition;
1152 } else {
1153 process_function = &Session::process_with_events;
1157 if (ptw & PostTransportStop) {
1159 transport_sub_state = 0;
1162 if (ptw & PostTransportLocate) {
1164 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1165 start_transport ();
1167 } else {
1168 transport_sub_state = 0;
1172 set_next_event ();
1173 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1174 know were handled ?
1176 set_post_transport_work (PostTransportWork (0));
1179 void
1180 Session::reset_rf_scale (nframes_t motion)
1182 cumulative_rf_motion += motion;
1184 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1185 rf_scale = 1;
1186 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1187 rf_scale = 4;
1188 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1189 rf_scale = 10;
1190 } else {
1191 rf_scale = 100;
1194 if (motion != 0) {
1195 set_dirty();
1199 void
1200 Session::use_sync_source (Slave* new_slave)
1202 /* Runs in process() context */
1204 bool non_rt_required = false;
1206 /* XXX this deletion is problematic because we're in RT context */
1208 delete _slave;
1209 _slave = new_slave;
1211 boost::shared_ptr<RouteList> rl = routes.reader();
1212 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1213 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1214 if (tr && !tr->hidden()) {
1215 if (tr->realtime_set_speed (tr->speed(), true)) {
1216 non_rt_required = true;
1218 tr->set_slaved (_slave != 0);
1222 if (non_rt_required) {
1223 add_post_transport_work (PostTransportSpeed);
1224 _butler->schedule_transport_work ();
1227 set_dirty();
1230 void
1231 Session::drop_sync_source ()
1233 request_sync_source (0);
1236 void
1237 Session::switch_to_sync_source (SyncSource src)
1239 Slave* new_slave;
1241 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1243 switch (src) {
1244 case MTC:
1245 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1246 return;
1249 if (_mtc_input_port) {
1250 try {
1251 new_slave = new MTC_Slave (*this, *_mtc_input_port);
1254 catch (failed_constructor& err) {
1255 return;
1258 } else {
1259 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1260 return;
1262 break;
1264 case MIDIClock:
1265 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1266 return;
1269 if (_midi_clock_input_port) {
1270 try {
1271 new_slave = new MIDIClock_Slave (*this, *_midi_clock_input_port, 24);
1274 catch (failed_constructor& err) {
1275 return;
1278 } else {
1279 error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
1280 return;
1282 break;
1284 case JACK:
1285 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1286 return;
1289 new_slave = new JACK_Slave (_engine.jack());
1290 break;
1292 default:
1293 new_slave = 0;
1294 break;
1297 request_sync_source (new_slave);
1300 void
1301 Session::reverse_track_buffers ()
1303 add_post_transport_work (PostTransportReverse);
1304 _butler->schedule_transport_work ();
1307 void
1308 Session::set_track_speed (Track* track, double speed)
1310 if (track->realtime_set_speed (speed, false)) {
1311 add_post_transport_work (PostTransportSpeed);
1312 _butler->schedule_transport_work ();
1313 set_dirty ();
1317 void
1318 Session::unset_play_range ()
1320 _play_range = false;
1321 _clear_event_type (SessionEvent::RangeStop);
1322 _clear_event_type (SessionEvent::RangeLocate);
1325 void
1326 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1328 SessionEvent* ev;
1330 /* Called from event-processing context */
1332 unset_play_range ();
1334 if (range.empty()) {
1335 /* _play_range set to false in unset_play_range()
1337 if (!leave_rolling) {
1338 /* stop transport */
1339 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1340 merge_event (ev);
1342 return;
1345 _play_range = true;
1347 /* cancel loop play */
1348 unset_play_loop ();
1350 list<AudioRange>::size_type sz = range.size();
1352 if (sz > 1) {
1354 list<AudioRange>::iterator i = range.begin();
1355 list<AudioRange>::iterator next;
1357 while (i != range.end()) {
1359 next = i;
1360 ++next;
1362 /* locating/stopping is subject to delays for declicking.
1365 nframes_t requested_frame = (*i).end;
1367 if (requested_frame > current_block_size) {
1368 requested_frame -= current_block_size;
1369 } else {
1370 requested_frame = 0;
1373 if (next == range.end()) {
1374 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1375 } else {
1376 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1379 merge_event (ev);
1381 i = next;
1384 } else if (sz == 1) {
1386 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1387 merge_event (ev);
1391 /* save range so we can do auto-return etc. */
1393 current_audio_range = range;
1395 /* now start rolling at the right place */
1397 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1398 merge_event (ev);
1400 TransportStateChange ();
1403 void
1404 Session::request_bounded_roll (nframes_t start, nframes_t end)
1406 AudioRange ar (start, end, 0);
1407 list<AudioRange> lar;
1409 lar.push_back (ar);
1410 request_play_range (&lar, true);
1412 void
1413 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1415 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1416 ev->target2_frame = start;
1417 queue_event (ev);
1420 void
1421 Session::engine_halted ()
1423 bool ignored;
1425 /* there will be no more calls to process(), so
1426 we'd better clean up for ourselves, right now.
1428 but first, make sure the butler is out of
1429 the picture.
1432 g_atomic_int_set (&_butler->should_do_transport_work, 0);
1433 set_post_transport_work (PostTransportWork (0));
1434 _butler->stop ();
1436 realtime_stop (false, true);
1437 non_realtime_stop (false, 0, ignored);
1438 transport_sub_state = 0;
1440 TransportStateChange (); /* EMIT SIGNAL */
1444 void
1445 Session::xrun_recovery ()
1447 // can't cast away volatile so copy and emit that
1448 nframes64_t tframe = _transport_frame;
1449 Xrun (tframe); //EMIT SIGNAL
1451 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1453 /* it didn't actually halt, but we need
1454 to handle things in the same way.
1457 engine_halted();
1461 void
1462 Session::route_processors_changed (RouteProcessorChange c)
1464 if (c.type == RouteProcessorChange::MeterPointChange) {
1465 return;
1468 update_latency_compensation (false, false);
1469 resort_routes ();
1472 void
1473 Session::update_latency_compensation (bool with_stop, bool abort)
1475 bool update_jack = false;
1476 PostTransportWork ptw;
1478 if (_state_of_the_state & Deletion) {
1479 return;
1482 _worst_track_latency = 0;
1483 ptw = post_transport_work();
1485 #undef DEBUG_LATENCY
1486 #ifdef DEBUG_LATENCY
1487 cerr << "\n---------------------------------\nUPDATE LATENCY\n";
1488 #endif
1490 boost::shared_ptr<RouteList> r = routes.reader ();
1492 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1494 if (with_stop) {
1495 (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
1498 nframes_t old_latency = (*i)->output()->signal_latency ();
1499 nframes_t track_latency = (*i)->update_total_latency ();
1501 if (old_latency != track_latency) {
1502 (*i)->input()->update_port_total_latencies ();
1503 (*i)->output()->update_port_total_latencies ();
1504 update_jack = true;
1507 if (!(*i)->is_hidden() && ((*i)->active())) {
1508 _worst_track_latency = max (_worst_track_latency, track_latency);
1512 if (update_jack) {
1513 _engine.update_total_latencies ();
1516 #ifdef DEBUG_LATENCY
1517 cerr << "\tworst was " << _worst_track_latency << endl;
1518 #endif
1520 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1521 (*i)->set_latency_delay (_worst_track_latency);
1524 set_worst_io_latencies ();
1526 /* reflect any changes in latencies into capture offsets
1529 boost::shared_ptr<RouteList> rl = routes.reader();
1530 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1531 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1532 if (tr) {
1533 tr->set_capture_offset ();
1538 void
1539 Session::allow_auto_play (bool yn)
1541 auto_play_legal = yn;
1544 void
1545 Session::reset_jack_connection (jack_client_t* jack)
1547 JACK_Slave* js;
1549 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1550 js->reset_client (jack);
1554 bool
1555 Session::maybe_stop (nframes_t limit)
1557 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1558 if (synced_to_jack () && config.get_jack_time_master ()) {
1559 _engine.transport_stop ();
1560 } else if (!synced_to_jack ()) {
1561 stop_transport ();
1563 return true;
1565 return false;
1568 void
1569 Session::send_mmc_locate (nframes64_t t)
1571 Timecode::Time time;
1572 timecode_time_subframes (t, time);
1573 _mmc->send (MIDI::MachineControlCommand (time));