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.
25 #include <sigc++/bind.h>
26 #include <sigc++/retype.h>
29 #include <pbd/error.h>
30 #include <pbd/lockmonitor.h>
31 #include <pbd/pthread_utils.h>
33 #include <midi++/mmc.h>
34 #include <midi++/port.h>
36 #include <ardour/ardour.h>
37 #include <ardour/audioengine.h>
38 #include <ardour/session.h>
39 #include <ardour/diskstream.h>
40 #include <ardour/auditioner.h>
41 #include <ardour/slave.h>
42 #include <ardour/location.h>
47 using namespace ARDOUR;
51 Session::request_input_change_handling ()
53 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
58 Session::request_slave_source (SlaveSource src, jack_nframes_t pos)
60 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, pos, 0.0);
62 if (src == Session::JACK) {
63 /* could set_seamless_loop() be disposed of entirely?*/
64 set_seamless_loop (false);
67 set_seamless_loop (true);
74 Session::request_transport_speed (float speed)
76 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
81 Session::request_diskstream_speed (DiskStream& ds, float speed)
83 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
89 Session::request_stop (bool abort)
91 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
96 Session::request_locate (jack_nframes_t target_frame, bool with_roll)
98 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
103 Session::force_locate (jack_nframes_t target_frame, bool with_roll)
105 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
110 Session::request_auto_loop (bool yn)
113 Location *location = _locations.auto_loop_location();
115 if (location == 0 && yn) {
116 error << _("Cannot loop - no loop range defined")
121 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
124 if (!yn && seamless_loop && transport_rolling()) {
125 // request an immediate locate to refresh the diskstreams
126 // after disabling looping
127 request_locate (_transport_frame-1, true);
132 Session::set_seamless_loop (bool yn)
134 if (seamless_loop != yn) {
137 if (auto_loop && transport_rolling()) {
138 // to reset diskstreams etc
139 request_auto_loop (true);
142 ControlChanged (SeamlessLoop); /* EMIT */
147 Session::realtime_stop (bool abort)
149 /* assume that when we start, we'll be moving forwards */
151 if (_transport_speed < 0.0f) {
152 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
154 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
157 if (actively_recording()) {
159 /* move the transport position back to where the
160 request for a stop was noticed. we rolled
161 past that point to pick up delayed input.
164 #ifndef LEAVE_TRANSPORT_UNADJUSTED
165 decrement_transport_position (_worst_output_latency);
168 /* the duration change is not guaranteed to have happened, but is likely */
170 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
174 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
177 _clear_event_type (Event::StopOnce);
178 _clear_event_type (Event::RangeStop);
179 _clear_event_type (Event::RangeLocate);
181 disable_record (true);
183 reset_slave_state ();
185 _transport_speed = 0;
187 transport_sub_state = (auto_return ? AutoReturning : 0);
191 Session::butler_transport_work ()
193 RWLockMonitor rm (route_lock, false, __LINE__, __FILE__);
194 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
196 if (post_transport_work & PostTransportCurveRealloc) {
197 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
198 (*i)->curve_reallocate();
202 if (post_transport_work & PostTransportInputChange) {
203 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
204 (*i)->non_realtime_input_change ();
208 if (post_transport_work & PostTransportSpeed) {
209 non_realtime_set_speed ();
212 if (post_transport_work & PostTransportReverse) {
216 cumulative_rf_motion = 0;
219 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
220 if (!(*i)->hidden()) {
221 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
222 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
225 (*i)->seek (_transport_frame);
231 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
232 non_realtime_stop (post_transport_work & PostTransportAbort);
235 if (post_transport_work & PostTransportOverWrite) {
236 non_realtime_overwrite ();
239 if (post_transport_work & PostTransportAudition) {
240 non_realtime_set_audition ();
243 atomic_dec (&butler_should_do_transport_work);
247 Session::non_realtime_set_speed ()
249 RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
251 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
252 (*i)->non_realtime_set_speed ();
257 Session::non_realtime_overwrite ()
259 RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
261 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
262 if ((*i)->pending_overwrite) {
263 (*i)->overwrite_existing_buffers ();
269 Session::non_realtime_stop (bool abort)
277 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
278 if ((*i)->get_captured_frames () != 0) {
284 /* stop and locate are merged here because they share a lot of common stuff */
287 now = localtime (&xnow);
290 auditioner->cancel_audition ();
294 cumulative_rf_motion = 0;
298 begin_reversible_command ("capture");
300 Location* loc = _locations.end_location();
301 bool change_end = false;
303 if (_transport_frame < loc->end()) {
305 /* stopped recording before current end */
307 if (_end_location_is_free) {
309 /* first capture for this session, move end back to where we are */
314 } else if (_transport_frame > loc->end()) {
316 /* stopped recording after the current end, extend it */
322 add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
323 add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
326 _end_location_is_free = false;
327 _have_captured = true;
330 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
331 (*i)->transport_stopped (*now, xnow, abort);
334 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
335 if (!(*i)->hidden()) {
336 (*i)->set_pending_declick (0);
341 commit_reversible_command ();
344 if (_engine.running()) {
345 update_latency_compensation (true, abort);
348 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
350 if (pending_locate_flush) {
351 flush_all_redirects ();
354 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
356 _transport_frame = last_stop_frame;
358 if (synced_to_jack()) {
359 _engine.transport_locate (_transport_frame);
363 #ifndef LEAVE_TRANSPORT_UNADJUSTED
367 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
368 if (!(*i)->hidden()) {
369 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
370 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
373 (*i)->seek (_transport_frame);
379 //deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
381 #ifdef LEAVE_TRANSPORT_UNADJUSTED
385 last_stop_frame = _transport_frame;
388 send_full_time_code();
389 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
390 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
395 /* XXX its a little odd that we're doing this here
396 when realtime_stop(), which has already executed,
400 if (!Config->get_latched_record_enable()) {
401 atomic_set (&_record_status, Disabled);
403 atomic_set (&_record_status, Enabled);
405 RecordStateChanged (); /* emit signal */
408 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
409 /* capture start has been changed, so save pending state */
410 save_state ("", true);
413 /* always try to get rid of this */
415 remove_pending_capture_state ();
417 /* save the current state of things if appropriate */
420 save_state (_current_snapshot_name);
423 if (post_transport_work & PostTransportDuration) {
424 DurationChanged (); /* EMIT SIGNAL */
427 if (post_transport_work & PostTransportStop) {
430 /* do not turn off autoloop on stop */
434 PositionChanged (_transport_frame); /* EMIT SIGNAL */
435 TransportStateChange (); /* EMIT SIGNAL */
437 /* and start it up again if relevant */
439 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
440 request_transport_speed (1.0);
441 pending_locate_roll = false;
446 Session::check_declick_out ()
448 bool locate_required = transport_sub_state & PendingLocate;
450 /* this is called after a process() iteration. if PendingDeclickOut was set,
451 it means that we were waiting to declick the output (which has just been
452 done) before doing something else. this is where we do that "something else".
454 note: called from the audio thread.
457 if (transport_sub_state & PendingDeclickOut) {
459 if (locate_required) {
460 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
461 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
463 stop_transport (pending_abort);
464 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
470 Session::set_auto_loop (bool yn)
472 /* Called from event-handling context */
474 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
480 if (yn && seamless_loop && synced_to_jack()) {
481 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
482 "Recommend changing the configured options")
488 if ((auto_loop = yn)) {
493 if ((loc = _locations.auto_loop_location()) != 0) {
496 // set all diskstreams to use internal looping
497 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
498 if (!(*i)->hidden()) {
499 (*i)->set_loop (loc);
504 // set all diskstreams to NOT use internal looping
505 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
506 if (!(*i)->hidden()) {
512 /* stick in the loop event */
514 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
517 /* locate to start of loop and roll if current pos is outside of the loop range */
518 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
519 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
523 // locate to current position (+ 1 to force reload)
524 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
532 clear_events (Event::AutoLoop);
534 // set all diskstreams to NOT use internal looping
535 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
536 if (!(*i)->hidden()) {
543 ControlChanged (AutoLoop); /* EMIT SIGNAL */
547 Session::flush_all_redirects ()
549 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
550 (*i)->flush_redirects ();
555 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
557 if (synced_to_jack()) {
562 _slave->speed_and_position (sp, pos);
564 if (target_frame != pos) {
566 /* tell JACK to change transport position, and we will
567 follow along later in ::follow_slave()
570 _engine.transport_locate (target_frame);
572 if (sp != 1.0f && with_roll) {
573 _engine.transport_start ();
580 locate (target_frame, with_roll, with_flush, with_loop);
585 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
587 if (actively_recording()) {
591 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
593 set_transport_speed (1.0, false);
595 loop_changing = false;
599 _transport_frame = target_frame;
600 smpte_time(_transport_frame, transmitting_smpte_time);
601 outbound_mtc_smpte_frame = _transport_frame;
602 next_quarter_frame_to_send = 0;
603 cerr << "[DR] LOCATE ----------" << endl;
604 cerr << "\t_transport_frame = " << _transport_frame << endl;
605 cerr << "\ttransmitting_smpte_time = " << string_compose("%1:%2:%3:%4",
606 transmitting_smpte_time.hours,transmitting_smpte_time.minutes,
607 transmitting_smpte_time.seconds,transmitting_smpte_time.frames) << endl;
608 cerr << "-------------" << endl;
610 if (_transport_speed && (!with_loop || loop_changing)) {
611 /* schedule a declick. we'll be called again when its done */
613 if (!(transport_sub_state & PendingDeclickOut)) {
614 transport_sub_state |= (PendingDeclickOut|PendingLocate);
615 pending_locate_frame = target_frame;
616 pending_locate_roll = with_roll;
617 pending_locate_flush = with_flush;
622 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
623 realtime_stop (false);
626 if ( !with_loop || loop_changing) {
628 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
631 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
634 schedule_butler_transport_work ();
638 /* this is functionally what clear_clicks() does but with a tentative lock */
640 TentativeRWLockMonitor clickm (click_lock, true, __LINE__, __FILE__);
642 if (clickm.locked()) {
644 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
653 /* switch from input if we're going to roll */
654 if (Config->get_use_hardware_monitoring()) {
655 /* Even though this is called from RT context we are using
656 a non-tentative rwlock here, because the action must occur.
657 The rarity and short potential lock duration makes this "OK"
659 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
660 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
661 if ((*i)->record_enabled ()) {
662 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
663 (*i)->monitor_input (!auto_input);
668 /* otherwise we're going to stop, so do the opposite */
669 if (Config->get_use_hardware_monitoring()) {
670 /* Even though this is called from RT context we are using
671 a non-tentative rwlock here, because the action must occur.
672 The rarity and short potential lock duration makes this "OK"
674 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
675 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
676 if ((*i)->record_enabled ()) {
677 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
678 (*i)->monitor_input (true);
684 /* cancel autoloop if transport pos outside of loop range */
686 Location* al = _locations.auto_loop_location();
688 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
689 // cancel looping directly, this is called from event handling context
690 set_auto_loop(false);
694 loop_changing = false;
696 _send_smpte_update = true;
700 Session::set_transport_speed (float speed, bool abort)
702 if (_transport_speed == speed) {
707 speed = min (8.0f, speed);
708 } else if (speed < 0) {
709 speed = max (-8.0f, speed);
712 if (transport_rolling() && speed == 0.0) {
714 if (Config->get_use_hardware_monitoring())
716 /* Even though this is called from RT context we are using
717 a non-tentative rwlock here, because the action must occur.
718 The rarity and short potential lock duration makes this "OK"
720 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
721 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
722 if ((*i)->record_enabled ()) {
723 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
724 (*i)->monitor_input (true);
729 if (synced_to_jack ()) {
730 _engine.transport_stop ();
732 stop_transport (abort);
735 } else if (transport_stopped() && speed == 1.0) {
737 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
741 if (Config->get_use_hardware_monitoring()) {
742 /* Even though this is called from RT context we are using
743 a non-tentative rwlock here, because the action must occur.
744 The rarity and short potential lock duration makes this "OK"
746 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
747 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
748 if (auto_input && (*i)->record_enabled ()) {
749 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
750 (*i)->monitor_input (false);
755 if (synced_to_jack()) {
756 _engine.transport_start ();
763 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
767 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
768 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
773 if (actively_recording()) {
777 if (speed > 0.0f && _transport_frame == current_end_frame()) {
781 if (speed < 0.0f && _transport_frame == 0) {
787 /* if we are reversing relative to the current speed, or relative to the speed
788 before the last stop, then we have to do extra work.
791 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
792 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
795 _last_transport_speed = _transport_speed;
796 _transport_speed = speed;
798 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
799 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
800 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
804 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
805 schedule_butler_transport_work ();
811 Session::stop_transport (bool abort)
813 if (_transport_speed == 0.0f) {
817 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
818 _worst_output_latency > current_block_size)
821 /* we need to capture the audio that has still not yet been received by the system
822 at the time the stop is requested, so we have to roll past that time.
824 we want to declick before stopping, so schedule the autostop for one
825 block before the actual end. we'll declick in the subsequent block,
826 and then we'll really be stopped.
829 Event *ev = new Event (Event::StopOnce, Event::Replace,
830 _transport_frame + _worst_output_latency - current_block_size,
834 transport_sub_state |= StopPendingCapture;
835 pending_abort = abort;
839 if ((transport_sub_state & PendingDeclickOut) == 0) {
840 transport_sub_state |= PendingDeclickOut;
841 /* we'll be called again after the declick */
845 realtime_stop (abort);
846 schedule_butler_transport_work ();
850 Session::start_transport ()
852 _last_roll_location = _transport_frame;
854 /* if record status is Enabled, move it to Recording. if its
855 already Recording, move it to Disabled.
858 switch (record_status()) {
866 disable_record (false);
873 if (!synced_to_jack() || _exporting) {
874 actually_start_transport ();
876 waiting_to_start = true;
881 Session::actually_start_transport ()
883 waiting_to_start = false;
885 transport_sub_state |= PendingDeclickIn;
886 _transport_speed = 1.0;
888 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
889 (*i)->realtime_set_speed ((*i)->speed(), true);
893 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
896 // [DR] Update SMPTE time from transport frame
897 smpte_time(_transport_frame, transmitting_smpte_time);
898 outbound_mtc_smpte_frame = _transport_frame;
899 next_quarter_frame_to_send = 0;
901 cerr << "[DR] ACTUALLY START TRANSPORT ----------" << endl;
902 cerr << "\t_transport_frame = " << _transport_frame << endl;
903 cerr << "\ttransmitting_smpte_time = " << string_compose("%1:%2:%3:%4",
904 transmitting_smpte_time.hours,transmitting_smpte_time.minutes,
905 transmitting_smpte_time.seconds,transmitting_smpte_time.frames) << endl;
906 cerr << "-------------" << endl;
908 TransportStateChange (); /* EMIT SIGNAL */
911 /** Do any transport work in the audio thread that needs to be done after the
912 * transport thread is finished. Audio thread, realtime safe.
915 Session::post_transport ()
917 if (post_transport_work & PostTransportAudition) {
918 if (auditioner && auditioner->active()) {
919 process_function = &Session::process_audition;
921 process_function = &Session::process_with_events;
925 if (post_transport_work & PostTransportStop) {
927 transport_sub_state = 0;
930 if (post_transport_work & PostTransportLocate) {
932 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
937 transport_sub_state = 0;
943 post_transport_work = PostTransportWork (0);
945 // [DR] Update SMPTE time from transport frame
946 smpte_time(_transport_frame, transmitting_smpte_time);
947 outbound_mtc_smpte_frame = _transport_frame;
948 next_quarter_frame_to_send = 0;
950 cerr << "[DR] POST TRANSPORT ----------" << endl;
951 cerr << "\t_transport_frame = " << _transport_frame << endl;
952 cerr << "\ttransmitting_smpte_time = " << string_compose("%1:%2:%3:%4",
953 transmitting_smpte_time.hours,transmitting_smpte_time.minutes,
954 transmitting_smpte_time.seconds,transmitting_smpte_time.frames) << endl;
955 cerr << "-------------" << endl;
959 Session::set_rf_speed (float speed)
962 cumulative_rf_motion = 0;
967 Session::reset_rf_scale (jack_nframes_t motion)
969 cumulative_rf_motion += motion;
971 if (cumulative_rf_motion < 4 * _current_frame_rate) {
973 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
975 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
987 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
989 bool reverse = false;
990 bool non_rt_required = false;
992 if (src == _slave_type) {
996 if (_transport_speed) {
997 error << _("please stop the transport before adjusting slave settings") << endmsg;
998 /* help out non-MVC friendly UI's by telling them the slave type changed */
999 ControlChanged (SlaveType); /* EMIT SIGNAL */
1003 // if (src == JACK && Config->get_jack_time_master()) {
1013 if (_transport_speed < 0.0) {
1025 _slave = new MTC_Slave (*this, *_mtc_port);
1028 catch (failed_constructor& err) {
1033 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1036 _desired_transport_speed = _transport_speed;
1040 _slave = new JACK_Slave (_engine.jack());
1041 _desired_transport_speed = _transport_speed;
1047 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1048 if (!(*i)->hidden()) {
1049 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1050 non_rt_required = true;
1052 (*i)->set_slaved (_slave);
1057 reverse_diskstream_buffers ();
1060 if (non_rt_required) {
1061 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1062 schedule_butler_transport_work ();
1066 ControlChanged (SlaveType); /* EMIT SIGNAL */
1072 Session::reverse_diskstream_buffers ()
1074 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1075 schedule_butler_transport_work ();
1079 Session::set_diskstream_speed (DiskStream* stream, float speed)
1081 if (stream->realtime_set_speed (speed, false)) {
1082 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1083 schedule_butler_transport_work ();
1089 Session::set_audio_range (list<AudioRange>& range)
1091 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1092 ev->audio_range = range;
1097 Session::request_play_range (bool yn)
1099 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1104 Session::set_play_range (bool yn)
1106 /* Called from event-processing context */
1108 if (_play_range != yn) {
1113 /* stop transport */
1114 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1118 ControlChanged (PlayRange); /* EMIT SIGNAL */
1123 Session::setup_auto_play ()
1125 /* Called from event-processing context */
1129 _clear_event_type (Event::RangeStop);
1130 _clear_event_type (Event::RangeLocate);
1136 list<AudioRange>::size_type sz = current_audio_range.size();
1140 list<AudioRange>::iterator i = current_audio_range.begin();
1141 list<AudioRange>::iterator next;
1143 while (i != current_audio_range.end()) {
1148 /* locating/stopping is subject to delays for declicking.
1151 jack_nframes_t requested_frame = (*i).end;
1153 if (requested_frame > current_block_size) {
1154 requested_frame -= current_block_size;
1156 requested_frame = 0;
1159 if (next == current_audio_range.end()) {
1160 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1162 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1170 } else if (sz == 1) {
1172 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1177 /* now start rolling at the right place */
1179 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1184 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1187 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1189 request_locate (start, true);
1193 Session::engine_halted ()
1195 /* there will be no more calls to process(), so
1196 we'd better clean up for ourselves, right now.
1198 but first, make sure the butler is out of
1202 atomic_set (&butler_should_do_transport_work, 0);
1203 post_transport_work = PostTransportWork (0);
1206 realtime_stop (false);
1207 non_realtime_stop (false);
1208 transport_sub_state = 0;
1210 TransportStateChange (); /* EMIT SIGNAL */
1215 Session::xrun_recovery ()
1217 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1219 HaltOnXrun (); /* EMIT SIGNAL */
1221 /* it didn't actually halt, but we need
1222 to handle things in the same way.
1230 Session::update_latency_compensation (bool with_stop, bool abort)
1232 bool update_jack = false;
1234 if (_state_of_the_state & Deletion) {
1238 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
1239 RWLockMonitor lm2 (diskstream_lock, false, __LINE__, __FILE__);
1240 _worst_track_latency = 0;
1242 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1244 (*i)->transport_stopped (abort, (post_transport_work & PostTransportLocate),
1245 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1248 jack_nframes_t old_latency = (*i)->signal_latency ();
1249 jack_nframes_t track_latency = (*i)->update_total_latency ();
1251 if (old_latency != track_latency) {
1255 if (!(*i)->hidden() && ((*i)->active())) {
1256 _worst_track_latency = max (_worst_track_latency, track_latency);
1260 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1261 (*i)->set_latency_delay (_worst_track_latency);
1264 /* tell JACK to play catch up */
1267 _engine.update_total_latencies ();
1270 set_worst_io_latencies (false);
1272 /* reflect any changes in latencies into capture offsets
1275 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1276 (*i)->set_capture_offset ();
1281 Session::update_latency_compensation_proxy (void* ignored)
1283 update_latency_compensation (false, false);