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);
192 disable_record (true);
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 /* always try to get rid of this */
410 remove_pending_capture_state ();
412 /* save the current state of things if appropriate */
415 save_state (_current_snapshot_name);
418 if (post_transport_work & PostTransportDuration) {
419 DurationChanged (); /* EMIT SIGNAL */
422 if (post_transport_work & PostTransportStop) {
425 /* do not turn off autoloop on stop */
429 PositionChanged (_transport_frame); /* EMIT SIGNAL */
430 TransportStateChange (); /* EMIT SIGNAL */
432 /* and start it up again if relevant */
434 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
435 request_transport_speed (1.0);
436 pending_locate_roll = false;
441 Session::check_declick_out ()
443 bool locate_required = transport_sub_state & PendingLocate;
445 /* this is called after a process() iteration. if PendingDeclickOut was set,
446 it means that we were waiting to declick the output (which has just been
447 done) before doing something else. this is where we do that "something else".
449 note: called from the audio thread.
452 if (transport_sub_state & PendingDeclickOut) {
454 if (locate_required) {
455 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
456 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
458 stop_transport (pending_abort);
459 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
465 Session::set_auto_loop (bool yn)
467 /* Called from event-handling context */
469 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
475 if (yn && seamless_loop && synced_to_jack()) {
476 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
477 "Recommend changing the configured options")
483 if ((auto_loop = yn)) {
488 if ((loc = _locations.auto_loop_location()) != 0) {
491 // set all diskstreams to use internal looping
492 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
493 if (!(*i)->hidden()) {
494 (*i)->set_loop (loc);
499 // set all diskstreams to NOT use internal looping
500 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
501 if (!(*i)->hidden()) {
507 /* stick in the loop event */
509 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
512 /* locate to start of loop and roll if current pos is outside of the loop range */
513 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
514 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
518 // locate to current position (+ 1 to force reload)
519 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
527 clear_events (Event::AutoLoop);
529 // set all diskstreams to NOT use internal looping
530 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
531 if (!(*i)->hidden()) {
538 ControlChanged (AutoLoop); /* EMIT SIGNAL */
542 Session::flush_all_redirects ()
544 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
545 (*i)->flush_redirects ();
550 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
552 if (synced_to_jack()) {
557 _slave->speed_and_position (sp, pos);
559 if (target_frame != pos) {
561 /* tell JACK to change transport position, and we will
562 follow along later in ::follow_slave()
565 _engine.transport_locate (target_frame);
567 if (sp != 1.0f && with_roll) {
568 _engine.transport_start ();
575 locate (target_frame, with_roll, with_flush, with_loop);
580 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
582 if (actively_recording()) {
586 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
588 set_transport_speed (1.0, false);
590 loop_changing = false;
594 _transport_frame = target_frame;
596 if (_transport_speed && (!with_loop || loop_changing)) {
597 /* schedule a declick. we'll be called again when its done */
599 if (!(transport_sub_state & PendingDeclickOut)) {
600 transport_sub_state |= (PendingDeclickOut|PendingLocate);
601 pending_locate_frame = target_frame;
602 pending_locate_roll = with_roll;
603 pending_locate_flush = with_flush;
608 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
609 realtime_stop (false);
612 if ( !with_loop || loop_changing) {
614 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
617 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
620 schedule_butler_transport_work ();
624 /* this is functionally what clear_clicks() does but with a tentative lock */
626 TentativeRWLockMonitor clickm (click_lock, true, __LINE__, __FILE__);
628 if (clickm.locked()) {
630 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
639 /* switch from input if we're going to roll */
640 if (Config->get_use_hardware_monitoring()) {
641 /* Even though this is called from RT context we are using
642 a non-tentative rwlock here, because the action must occur.
643 The rarity and short potential lock duration makes this "OK"
645 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
646 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
647 if ((*i)->record_enabled ()) {
648 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
649 (*i)->monitor_input (!auto_input);
654 /* otherwise we're going to stop, so do the opposite */
655 if (Config->get_use_hardware_monitoring()) {
656 /* Even though this is called from RT context we are using
657 a non-tentative rwlock here, because the action must occur.
658 The rarity and short potential lock duration makes this "OK"
660 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
661 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
662 if ((*i)->record_enabled ()) {
663 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
664 (*i)->monitor_input (true);
670 /* cancel autoloop if transport pos outside of loop range */
672 Location* al = _locations.auto_loop_location();
674 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
675 // cancel looping directly, this is called from event handling context
676 set_auto_loop(false);
680 loop_changing = false;
684 Session::set_transport_speed (float speed, bool abort)
686 if (_transport_speed == speed) {
691 speed = min (8.0f, speed);
692 } else if (speed < 0) {
693 speed = max (-8.0f, speed);
696 if (transport_rolling() && speed == 0.0) {
698 if (Config->get_use_hardware_monitoring())
700 /* Even though this is called from RT context we are using
701 a non-tentative rwlock here, because the action must occur.
702 The rarity and short potential lock duration makes this "OK"
704 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
705 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
706 if ((*i)->record_enabled ()) {
707 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
708 (*i)->monitor_input (true);
713 if (synced_to_jack ()) {
714 _engine.transport_stop ();
716 stop_transport (abort);
719 } else if (transport_stopped() && speed == 1.0) {
721 if (Config->get_use_hardware_monitoring()) {
722 /* Even though this is called from RT context we are using
723 a non-tentative rwlock here, because the action must occur.
724 The rarity and short potential lock duration makes this "OK"
726 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
727 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
728 if (auto_input && (*i)->record_enabled ()) {
729 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
730 (*i)->monitor_input (false);
735 if (synced_to_jack()) {
736 _engine.transport_start ();
743 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
744 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
749 if (actively_recording()) {
753 if (speed > 0.0f && _transport_frame == current_end_frame()) {
757 if (speed < 0.0f && _transport_frame == 0) {
763 /* if we are reversing relative to the current speed, or relative to the speed
764 before the last stop, then we have to do extra work.
767 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
768 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
771 _last_transport_speed = _transport_speed;
772 _transport_speed = speed;
774 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
775 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
776 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
780 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
781 schedule_butler_transport_work ();
787 Session::stop_transport (bool abort)
789 if (_transport_speed == 0.0f) {
793 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
794 _worst_output_latency > current_block_size)
797 /* we need to capture the audio that has still not yet been received by the system
798 at the time the stop is requested, so we have to roll past that time.
800 we want to declick before stopping, so schedule the autostop for one
801 block before the actual end. we'll declick in the subsequent block,
802 and then we'll really be stopped.
805 Event *ev = new Event (Event::StopOnce, Event::Replace,
806 _transport_frame + _worst_output_latency - current_block_size,
810 transport_sub_state |= StopPendingCapture;
811 pending_abort = abort;
815 if ((transport_sub_state & PendingDeclickOut) == 0) {
816 transport_sub_state |= PendingDeclickOut;
817 /* we'll be called again after the declick */
821 realtime_stop (abort);
822 schedule_butler_transport_work ();
826 Session::start_transport ()
828 _last_roll_location = _transport_frame;
830 /* if record status is Enabled, move it to Recording. if its
831 already Recording, move it to Disabled.
834 switch (record_status()) {
842 disable_record (false);
849 if (!synced_to_jack() || _exporting) {
850 actually_start_transport ();
852 waiting_to_start = true;
857 Session::actually_start_transport ()
859 waiting_to_start = false;
861 transport_sub_state |= PendingDeclickIn;
862 _transport_speed = 1.0;
864 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
865 (*i)->realtime_set_speed ((*i)->speed(), true);
868 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
870 TransportStateChange (); /* EMIT SIGNAL */
874 Session::post_transport ()
876 if (post_transport_work & PostTransportAudition) {
877 if (auditioner && auditioner->active()) {
878 process_function = &Session::process_audition;
880 process_function = &Session::process_with_events;
884 if (post_transport_work & PostTransportStop) {
886 transport_sub_state = 0;
889 if (post_transport_work & PostTransportLocate) {
891 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
896 transport_sub_state = 0;
902 post_transport_work = PostTransportWork (0);
906 Session::set_rf_speed (float speed)
909 cumulative_rf_motion = 0;
914 Session::reset_rf_scale (jack_nframes_t motion)
916 cumulative_rf_motion += motion;
918 if (cumulative_rf_motion < 4 * _current_frame_rate) {
920 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
922 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
934 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
936 bool reverse = false;
937 bool non_rt_required = false;
939 if (_transport_speed) {
940 error << _("please stop the transport before adjusting slave settings") << endmsg;
941 /* help out non-MVC friendly UI's by telling them the slave type changed */
942 ControlChanged (SlaveType); /* EMIT SIGNAL */
946 if (src == _slave_type) {
950 // if (src == JACK && Config->get_jack_time_master()) {
960 if (_transport_speed < 0.0) {
972 _slave = new MTC_Slave (*this, *_mtc_port);
975 catch (failed_constructor& err) {
980 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
983 _desired_transport_speed = _transport_speed;
987 _slave = new JACK_Slave (_engine.jack());
988 _desired_transport_speed = _transport_speed;
994 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
995 if (!(*i)->hidden()) {
996 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
997 non_rt_required = true;
999 (*i)->set_slaved (_slave);
1004 reverse_diskstream_buffers ();
1007 if (non_rt_required) {
1008 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1009 schedule_butler_transport_work ();
1013 ControlChanged (SlaveType); /* EMIT SIGNAL */
1019 Session::reverse_diskstream_buffers ()
1021 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1022 schedule_butler_transport_work ();
1026 Session::set_diskstream_speed (DiskStream* stream, float speed)
1028 if (stream->realtime_set_speed (speed, false)) {
1029 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1030 schedule_butler_transport_work ();
1036 Session::set_audio_range (list<AudioRange>& range)
1038 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1039 ev->audio_range = range;
1044 Session::request_play_range (bool yn)
1046 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1051 Session::set_play_range (bool yn)
1053 /* Called from event-processing context */
1055 if (_play_range != yn) {
1060 /* stop transport */
1061 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1065 ControlChanged (PlayRange); /* EMIT SIGNAL */
1070 Session::setup_auto_play ()
1072 /* Called from event-processing context */
1076 _clear_event_type (Event::RangeStop);
1077 _clear_event_type (Event::RangeLocate);
1083 list<AudioRange>::size_type sz = current_audio_range.size();
1087 list<AudioRange>::iterator i = current_audio_range.begin();
1088 list<AudioRange>::iterator next;
1090 while (i != current_audio_range.end()) {
1095 /* locating/stopping is subject to delays for declicking.
1098 jack_nframes_t requested_frame = (*i).end;
1100 if (requested_frame > current_block_size) {
1101 requested_frame -= current_block_size;
1103 requested_frame = 0;
1106 if (next == current_audio_range.end()) {
1107 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1109 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1117 } else if (sz == 1) {
1119 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1124 /* now start rolling at the right place */
1126 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1131 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1134 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1136 request_locate (start, true);
1140 Session::engine_halted ()
1142 /* there will be no more calls to process(), so
1143 we'd better clean up for ourselves, right now.
1145 but first, make sure the butler is out of
1149 atomic_set (&butler_should_do_transport_work, 0);
1150 post_transport_work = PostTransportWork (0);
1153 realtime_stop (false);
1154 non_realtime_stop (false);
1155 transport_sub_state = 0;
1157 TransportStateChange (); /* EMIT SIGNAL */
1162 Session::xrun_recovery ()
1164 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1166 HaltOnXrun (); /* EMIT SIGNAL */
1168 /* it didn't actually halt, but we need
1169 to handle things in the same way.
1177 Session::update_latency_compensation (bool with_stop, bool abort)
1179 bool update_jack = false;
1181 if (_state_of_the_state & Deletion) {
1185 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
1186 RWLockMonitor lm2 (diskstream_lock, false, __LINE__, __FILE__);
1187 _worst_track_latency = 0;
1189 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1191 (*i)->transport_stopped (abort, (post_transport_work & PostTransportLocate),
1192 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1195 jack_nframes_t old_latency = (*i)->signal_latency ();
1196 jack_nframes_t track_latency = (*i)->update_total_latency ();
1198 if (old_latency != track_latency) {
1202 if (!(*i)->hidden() && ((*i)->active())) {
1203 _worst_track_latency = max (_worst_track_latency, track_latency);
1207 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1208 (*i)->set_latency_delay (_worst_track_latency);
1211 /* tell JACK to play catch up */
1214 _engine.update_total_latencies ();
1217 set_worst_io_latencies (false);
1219 /* reflect any changes in latencies into capture offsets
1222 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1223 (*i)->set_capture_offset ();
1228 Session::update_latency_compensation_proxy (void* ignored)
1230 update_latency_compensation (false, false);