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 if (_transport_frame > current_end_frame()) {
170 /* first capture resets end location; later captures can only extend the length */
172 if (_end_location_is_free) {
173 end_location->set_end (_transport_frame);
174 _end_location_is_free = false;
175 } else if (_transport_frame > end_location->start()) {
176 end_location->set_end (_transport_frame);
179 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
185 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
188 _clear_event_type (Event::StopOnce);
189 _clear_event_type (Event::RangeStop);
190 _clear_event_type (Event::RangeLocate);
194 reset_slave_state ();
196 _transport_speed = 0;
198 transport_sub_state = (auto_return ? AutoReturning : 0);
202 Session::butler_transport_work ()
204 RWLockMonitor rm (route_lock, false, __LINE__, __FILE__);
205 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
207 if (post_transport_work & PostTransportCurveRealloc) {
208 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
209 (*i)->curve_reallocate();
213 if (post_transport_work & PostTransportInputChange) {
214 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
215 (*i)->non_realtime_input_change ();
219 if (post_transport_work & PostTransportSpeed) {
220 non_realtime_set_speed ();
223 if (post_transport_work & PostTransportReverse) {
227 cumulative_rf_motion = 0;
230 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
231 if (!(*i)->hidden()) {
232 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
233 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
236 (*i)->seek (_transport_frame);
242 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
243 non_realtime_stop (post_transport_work & PostTransportAbort);
246 if (post_transport_work & PostTransportOverWrite) {
247 non_realtime_overwrite ();
250 if (post_transport_work & PostTransportAudition) {
251 non_realtime_set_audition ();
254 atomic_dec (&butler_should_do_transport_work);
258 Session::non_realtime_set_speed ()
260 RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
262 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
263 (*i)->non_realtime_set_speed ();
268 Session::non_realtime_overwrite ()
270 RWLockMonitor lm (diskstream_lock, false, __LINE__, __FILE__);
272 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
273 if ((*i)->pending_overwrite) {
274 (*i)->overwrite_existing_buffers ();
280 Session::non_realtime_stop (bool abort)
288 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
289 if ((*i)->get_captured_frames () != 0) {
295 /* stop and locate are merged here because they share a lot of common stuff */
298 now = localtime (&xnow);
301 auditioner->cancel_audition ();
305 cumulative_rf_motion = 0;
309 begin_reversible_command ("capture");
311 Location* loc = _locations.end_location();
313 if (loc && !_have_captured) {
317 note: later captures that extend the session length get
318 handled because of playlist length changes.
321 add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
322 add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
325 _have_captured = true;
328 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
329 (*i)->transport_stopped (*now, xnow, abort);
332 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
333 if (!(*i)->hidden()) {
334 (*i)->set_pending_declick (0);
339 commit_reversible_command ();
342 if (_engine.running()) {
343 update_latency_compensation (true, abort);
346 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
348 if (pending_locate_flush) {
349 flush_all_redirects ();
352 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
354 _transport_frame = last_stop_frame;
356 if (synced_to_jack()) {
357 _engine.transport_locate (_transport_frame);
361 #ifndef LEAVE_TRANSPORT_UNADJUSTED
365 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
366 if (!(*i)->hidden()) {
367 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
368 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
371 (*i)->seek (_transport_frame);
376 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
378 #ifdef LEAVE_TRANSPORT_UNADJUSTED
382 last_stop_frame = _transport_frame;
384 send_full_time_code ();
385 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
386 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
390 /* XXX its a little odd that we're doing this here
391 when realtime_stop(), which has already executed,
395 if (!Config->get_latched_record_enable()) {
396 atomic_set (&_record_status, Disabled);
398 atomic_set (&_record_status, Enabled);
400 RecordStateChanged (); /* emit signal */
403 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
404 /* capture start has been changed, so save pending state */
405 save_state ("", true);
408 /* save the current state of things if appropriate */
411 save_state (_current_snapshot_name);
414 if (post_transport_work & PostTransportDuration) {
415 DurationChanged (); /* EMIT SIGNAL */
418 if (post_transport_work & PostTransportStop) {
421 /* do not turn off autoloop on stop */
425 PositionChanged (_transport_frame); /* EMIT SIGNAL */
426 TransportStateChange (); /* EMIT SIGNAL */
428 /* and start it up again if relevant */
430 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
431 request_transport_speed (1.0);
432 pending_locate_roll = false;
437 Session::check_declick_out ()
439 bool locate_required = transport_sub_state & PendingLocate;
441 /* this is called after a process() iteration. if PendingDeclickOut was set,
442 it means that we were waiting to declick the output (which has just been
443 done) before doing something else. this is where we do that "something else".
445 note: called from the audio thread.
448 if (transport_sub_state & PendingDeclickOut) {
450 if (locate_required) {
451 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
452 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
454 stop_transport (pending_abort);
455 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
461 Session::set_auto_loop (bool yn)
463 /* Called from event-handling context */
465 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
471 if (yn && seamless_loop && synced_to_jack()) {
472 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
473 "Recommend changing the configured options")
479 if ((auto_loop = yn)) {
484 if ((loc = _locations.auto_loop_location()) != 0) {
487 // set all diskstreams to use internal looping
488 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
489 if (!(*i)->hidden()) {
490 (*i)->set_loop (loc);
495 // set all diskstreams to NOT use internal looping
496 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
497 if (!(*i)->hidden()) {
503 /* stick in the loop event */
505 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
508 /* locate to start of loop and roll if current pos is outside of the loop range */
509 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
510 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
514 // locate to current position (+ 1 to force reload)
515 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
523 clear_events (Event::AutoLoop);
525 // set all diskstreams to NOT use internal looping
526 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
527 if (!(*i)->hidden()) {
534 ControlChanged (AutoLoop); /* EMIT SIGNAL */
538 Session::flush_all_redirects ()
540 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
541 (*i)->flush_redirects ();
546 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
548 if (synced_to_jack()) {
553 _slave->speed_and_position (sp, pos);
555 if (target_frame != pos) {
557 /* tell JACK to change transport position, and we will
558 follow along later in ::follow_slave()
561 _engine.transport_locate (target_frame);
563 if (sp != 1.0f && with_roll) {
564 _engine.transport_start ();
571 locate (target_frame, with_roll, with_flush, with_loop);
576 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
578 if (actively_recording()) {
582 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
584 set_transport_speed (1.0, false);
586 loop_changing = false;
590 _transport_frame = target_frame;
592 if (_transport_speed && (!with_loop || loop_changing)) {
593 /* schedule a declick. we'll be called again when its done */
595 if (!(transport_sub_state & PendingDeclickOut)) {
596 transport_sub_state |= (PendingDeclickOut|PendingLocate);
597 pending_locate_frame = target_frame;
598 pending_locate_roll = with_roll;
599 pending_locate_flush = with_flush;
604 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
605 realtime_stop (false);
608 if ( !with_loop || loop_changing) {
610 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
613 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
616 schedule_butler_transport_work ();
620 /* this is functionally what clear_clicks() does but with a tentative lock */
622 TentativeRWLockMonitor clickm (click_lock, true, __LINE__, __FILE__);
624 if (clickm.locked()) {
626 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
635 /* switch from input if we're going to roll */
636 if (Config->get_use_hardware_monitoring()) {
637 /* Even though this is called from RT context we are using
638 a non-tentative rwlock here, because the action must occur.
639 The rarity and short potential lock duration makes this "OK"
641 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
642 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
643 if ((*i)->record_enabled ()) {
644 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
645 (*i)->monitor_input (!auto_input);
650 /* otherwise we're going to stop, so do the opposite */
651 if (Config->get_use_hardware_monitoring()) {
652 /* Even though this is called from RT context we are using
653 a non-tentative rwlock here, because the action must occur.
654 The rarity and short potential lock duration makes this "OK"
656 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
657 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
658 if ((*i)->record_enabled ()) {
659 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
660 (*i)->monitor_input (true);
666 /* cancel autoloop if transport pos outside of loop range */
668 Location* al = _locations.auto_loop_location();
670 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
671 // cancel looping directly, this is called from event handling context
672 set_auto_loop(false);
676 loop_changing = false;
680 Session::set_transport_speed (float speed, bool abort)
682 if (_transport_speed == speed) {
687 speed = min (8.0f, speed);
688 } else if (speed < 0) {
689 speed = max (-8.0f, speed);
692 if (transport_rolling() && speed == 0.0) {
694 if (Config->get_use_hardware_monitoring())
696 /* Even though this is called from RT context we are using
697 a non-tentative rwlock here, because the action must occur.
698 The rarity and short potential lock duration makes this "OK"
700 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
701 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
702 if ((*i)->record_enabled ()) {
703 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
704 (*i)->monitor_input (true);
709 if (synced_to_jack ()) {
710 _engine.transport_stop ();
712 stop_transport (abort);
715 } else if (transport_stopped() && speed == 1.0) {
717 if (Config->get_use_hardware_monitoring()) {
718 /* Even though this is called from RT context we are using
719 a non-tentative rwlock here, because the action must occur.
720 The rarity and short potential lock duration makes this "OK"
722 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
723 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
724 if (auto_input && (*i)->record_enabled ()) {
725 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
726 (*i)->monitor_input (false);
731 if (synced_to_jack()) {
732 _engine.transport_start ();
739 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
740 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
745 if (actively_recording()) {
749 if (speed > 0.0f && _transport_frame == current_end_frame()) {
753 if (speed < 0.0f && _transport_frame == 0) {
759 /* if we are reversing relative to the current speed, or relative to the speed
760 before the last stop, then we have to do extra work.
763 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
764 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
767 _last_transport_speed = _transport_speed;
768 _transport_speed = speed;
770 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
771 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
772 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
776 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
777 schedule_butler_transport_work ();
783 Session::stop_transport (bool abort)
785 if (_transport_speed == 0.0f) {
789 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
790 _worst_output_latency > current_block_size)
793 /* we need to capture the audio that has still not yet been received by the system
794 at the time the stop is requested, so we have to roll past that time.
796 we want to declick before stopping, so schedule the autostop for one
797 block before the actual end. we'll declick in the subsequent block,
798 and then we'll really be stopped.
801 Event *ev = new Event (Event::StopOnce, Event::Replace,
802 _transport_frame + _worst_output_latency - current_block_size,
806 transport_sub_state |= StopPendingCapture;
807 pending_abort = abort;
811 if ((transport_sub_state & PendingDeclickOut) == 0) {
812 transport_sub_state |= PendingDeclickOut;
813 /* we'll be called again after the declick */
817 realtime_stop (abort);
818 schedule_butler_transport_work ();
822 Session::start_transport ()
824 _last_roll_location = _transport_frame;
826 /* if record status is Enabled, move it to Recording. if its
827 already Recording, move it to Disabled.
830 switch (record_status()) {
845 if (!synced_to_jack() || _exporting) {
846 actually_start_transport ();
848 waiting_to_start = true;
853 Session::actually_start_transport ()
855 waiting_to_start = false;
857 transport_sub_state |= PendingDeclickIn;
858 _transport_speed = 1.0;
860 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
861 (*i)->realtime_set_speed ((*i)->speed(), true);
864 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
866 TransportStateChange (); /* EMIT SIGNAL */
870 Session::post_transport ()
872 if (post_transport_work & PostTransportAudition) {
873 if (auditioner && auditioner->active()) {
874 process_function = &Session::process_audition;
876 process_function = &Session::process_with_events;
880 if (post_transport_work & PostTransportStop) {
882 transport_sub_state = 0;
885 if (post_transport_work & PostTransportLocate) {
887 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
892 transport_sub_state = 0;
898 post_transport_work = PostTransportWork (0);
902 Session::set_rf_speed (float speed)
905 cumulative_rf_motion = 0;
910 Session::reset_rf_scale (jack_nframes_t motion)
912 cumulative_rf_motion += motion;
914 if (cumulative_rf_motion < 4 * _current_frame_rate) {
916 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
918 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
930 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
932 bool reverse = false;
933 bool non_rt_required = false;
935 if (_transport_speed) {
936 error << _("please stop the transport before adjusting slave settings") << endmsg;
937 /* help out non-MVC friendly UI's by telling them the slave type changed */
938 ControlChanged (SlaveType); /* EMIT SIGNAL */
942 if (src == _slave_type) {
946 // if (src == JACK && Config->get_jack_time_master()) {
956 if (_transport_speed < 0.0) {
968 _slave = new MTC_Slave (*this, *_mtc_port);
971 catch (failed_constructor& err) {
976 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
979 _desired_transport_speed = _transport_speed;
983 _slave = new JACK_Slave (_engine.jack());
984 _desired_transport_speed = _transport_speed;
990 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
991 if (!(*i)->hidden()) {
992 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
993 non_rt_required = true;
995 (*i)->set_slaved (_slave);
1000 reverse_diskstream_buffers ();
1003 if (non_rt_required) {
1004 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1005 schedule_butler_transport_work ();
1009 ControlChanged (SlaveType); /* EMIT SIGNAL */
1015 Session::reverse_diskstream_buffers ()
1017 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1018 schedule_butler_transport_work ();
1022 Session::set_diskstream_speed (DiskStream* stream, float speed)
1024 if (stream->realtime_set_speed (speed, false)) {
1025 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1026 schedule_butler_transport_work ();
1032 Session::set_audio_range (list<AudioRange>& range)
1034 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1035 ev->audio_range = range;
1040 Session::request_play_range (bool yn)
1042 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1047 Session::set_play_range (bool yn)
1049 /* Called from event-processing context */
1051 if (_play_range != yn) {
1056 /* stop transport */
1057 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1061 ControlChanged (PlayRange); /* EMIT SIGNAL */
1066 Session::setup_auto_play ()
1068 /* Called from event-processing context */
1072 _clear_event_type (Event::RangeStop);
1073 _clear_event_type (Event::RangeLocate);
1079 list<AudioRange>::size_type sz = current_audio_range.size();
1083 list<AudioRange>::iterator i = current_audio_range.begin();
1084 list<AudioRange>::iterator next;
1086 while (i != current_audio_range.end()) {
1091 /* locating/stopping is subject to delays for declicking.
1094 jack_nframes_t requested_frame = (*i).end;
1096 if (requested_frame > current_block_size) {
1097 requested_frame -= current_block_size;
1099 requested_frame = 0;
1102 if (next == current_audio_range.end()) {
1103 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1105 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1113 } else if (sz == 1) {
1115 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1120 /* now start rolling at the right place */
1122 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1127 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1130 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1132 request_locate (start, true);
1136 Session::engine_halted ()
1138 /* there will be no more calls to process(), so
1139 we'd better clean up for ourselves, right now.
1141 but first, make sure the butler is out of
1145 atomic_set (&butler_should_do_transport_work, 0);
1146 post_transport_work = PostTransportWork (0);
1149 realtime_stop (false);
1150 non_realtime_stop (false);
1151 transport_sub_state = 0;
1153 TransportStateChange (); /* EMIT SIGNAL */
1158 Session::xrun_recovery ()
1160 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1162 HaltOnXrun (); /* EMIT SIGNAL */
1164 /* it didn't actually halt, but we need
1165 to handle things in the same way.
1173 Session::update_latency_compensation (bool with_stop, bool abort)
1175 bool update_jack = false;
1177 if (_state_of_the_state & Deletion) {
1181 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
1182 RWLockMonitor lm2 (diskstream_lock, false, __LINE__, __FILE__);
1183 _worst_track_latency = 0;
1185 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1187 (*i)->transport_stopped (abort, (post_transport_work & PostTransportLocate),
1188 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1191 jack_nframes_t old_latency = (*i)->signal_latency ();
1192 jack_nframes_t track_latency = (*i)->update_total_latency ();
1194 if (old_latency != track_latency) {
1198 if (!(*i)->hidden() && ((*i)->active())) {
1199 _worst_track_latency = max (_worst_track_latency, track_latency);
1203 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1204 (*i)->set_latency_delay (_worst_track_latency);
1207 /* tell JACK to play catch up */
1210 _engine.update_total_latencies ();
1213 set_worst_io_latencies (false);
1215 /* reflect any changes in latencies into capture offsets
1218 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1219 (*i)->set_capture_offset ();
1224 Session::update_latency_compensation_proxy (void* ignored)
1226 update_latency_compensation (false, false);