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);
389 atomic_set (&_record_status, Disabled);
390 RecordDisabled (); /* EMIT SIGNAL */
393 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
394 /* capture start has been changed, so save pending state */
395 save_state ("", true);
398 /* save the current state of things if appropriate */
401 save_state (_current_snapshot_name);
404 if (post_transport_work & PostTransportDuration) {
405 DurationChanged (); /* EMIT SIGNAL */
408 if (post_transport_work & PostTransportStop) {
411 /* do not turn off autoloop on stop */
415 PositionChanged (_transport_frame); /* EMIT SIGNAL */
416 TransportStateChange (); /* EMIT SIGNAL */
418 /* and start it up again if relevant */
420 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
421 request_transport_speed (1.0);
422 pending_locate_roll = false;
427 Session::check_declick_out ()
429 bool locate_required = transport_sub_state & PendingLocate;
431 /* this is called after a process() iteration. if PendingDeclickOut was set,
432 it means that we were waiting to declick the output (which has just been
433 done) before doing something else. this is where we do that "something else".
435 note: called from the audio thread.
438 if (transport_sub_state & PendingDeclickOut) {
440 if (locate_required) {
441 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
442 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
444 stop_transport (pending_abort);
445 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
451 Session::set_auto_loop (bool yn)
453 /* Called from event-handling context */
455 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
461 if (yn && seamless_loop && synced_to_jack()) {
462 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
463 "Recommend changing the configured options")
469 if ((auto_loop = yn)) {
474 if ((loc = _locations.auto_loop_location()) != 0) {
477 // set all diskstreams to use internal looping
478 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
479 if (!(*i)->hidden()) {
480 (*i)->set_loop (loc);
485 // set all diskstreams to NOT use internal looping
486 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
487 if (!(*i)->hidden()) {
493 /* stick in the loop event */
495 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
498 /* locate to start of loop and roll if current pos is outside of the loop range */
499 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
500 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
504 // locate to current position (+ 1 to force reload)
505 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
513 clear_events (Event::AutoLoop);
515 // set all diskstreams to NOT use internal looping
516 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
517 if (!(*i)->hidden()) {
524 ControlChanged (AutoLoop); /* EMIT SIGNAL */
528 Session::flush_all_redirects ()
530 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
531 (*i)->flush_redirects ();
536 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
538 if (synced_to_jack()) {
543 _slave->speed_and_position (sp, pos);
545 if (target_frame != pos) {
547 /* tell JACK to change transport position, and we will
548 follow along later in ::follow_slave()
551 _engine.transport_locate (target_frame);
553 if (sp != 1.0f && with_roll) {
554 _engine.transport_start ();
561 locate (target_frame, with_roll, with_flush, with_loop);
566 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
568 if (actively_recording()) {
572 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
574 set_transport_speed (1.0, false);
576 loop_changing = false;
580 _transport_frame = target_frame;
582 if (_transport_speed && (!with_loop || loop_changing)) {
583 /* schedule a declick. we'll be called again when its done */
585 if (!(transport_sub_state & PendingDeclickOut)) {
586 transport_sub_state |= (PendingDeclickOut|PendingLocate);
587 pending_locate_frame = target_frame;
588 pending_locate_roll = with_roll;
589 pending_locate_flush = with_flush;
594 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
595 realtime_stop (false);
598 if ( !with_loop || loop_changing) {
600 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
603 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
606 schedule_butler_transport_work ();
610 /* this is functionally what clear_clicks() does but with a tentative lock */
612 TentativeRWLockMonitor clickm (click_lock, true, __LINE__, __FILE__);
614 if (clickm.locked()) {
616 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
625 /* switch from input if we're going to roll */
626 if (Config->get_use_hardware_monitoring()) {
627 /* Even though this is called from RT context we are using
628 a non-tentative rwlock here, because the action must occur.
629 The rarity and short potential lock duration makes this "OK"
631 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
632 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
633 if ((*i)->record_enabled ()) {
634 cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
635 (*i)->monitor_input (!auto_input);
640 /* otherwise we're going to stop, so do the opposite */
641 if (Config->get_use_hardware_monitoring()) {
642 /* Even though this is called from RT context we are using
643 a non-tentative rwlock here, because the action must occur.
644 The rarity and short potential lock duration makes this "OK"
646 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
647 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
648 if ((*i)->record_enabled ()) {
649 cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
650 (*i)->monitor_input (true);
656 /* cancel autoloop if transport pos outside of loop range */
658 Location* al = _locations.auto_loop_location();
660 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
661 // cancel looping directly, this is called from event handling context
662 set_auto_loop(false);
666 loop_changing = false;
670 Session::set_transport_speed (float speed, bool abort)
672 if (_transport_speed == speed) {
677 speed = min (8.0f, speed);
678 } else if (speed < 0) {
679 speed = max (-8.0f, speed);
682 if (transport_rolling() && speed == 0.0) {
684 if (Config->get_use_hardware_monitoring())
686 /* Even though this is called from RT context we are using
687 a non-tentative rwlock here, because the action must occur.
688 The rarity and short potential lock duration makes this "OK"
690 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
691 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
692 if ((*i)->record_enabled ()) {
693 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
694 (*i)->monitor_input (true);
699 if (synced_to_jack ()) {
700 _engine.transport_stop ();
702 stop_transport (abort);
705 } else if (transport_stopped() && speed == 1.0) {
707 if (Config->get_use_hardware_monitoring()) {
708 /* Even though this is called from RT context we are using
709 a non-tentative rwlock here, because the action must occur.
710 The rarity and short potential lock duration makes this "OK"
712 RWLockMonitor dsm (diskstream_lock, false, __LINE__, __FILE__);
713 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
714 if (auto_input && (*i)->record_enabled ()) {
715 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
716 (*i)->monitor_input (false);
721 if (synced_to_jack()) {
722 _engine.transport_start ();
729 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
730 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
735 if (actively_recording()) {
739 if (speed > 0.0f && _transport_frame == current_end_frame()) {
743 if (speed < 0.0f && _transport_frame == 0) {
749 /* if we are reversing relative to the current speed, or relative to the speed
750 before the last stop, then we have to do extra work.
753 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
754 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
757 _last_transport_speed = _transport_speed;
758 _transport_speed = speed;
760 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
761 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
762 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
766 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
767 schedule_butler_transport_work ();
773 Session::stop_transport (bool abort)
775 if (_transport_speed == 0.0f) {
779 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
780 _worst_output_latency > current_block_size)
783 /* we need to capture the audio that has still not yet been received by the system
784 at the time the stop is requested, so we have to roll past that time.
786 we want to declick before stopping, so schedule the autostop for one
787 block before the actual end. we'll declick in the subsequent block,
788 and then we'll really be stopped.
791 Event *ev = new Event (Event::StopOnce, Event::Replace,
792 _transport_frame + _worst_output_latency - current_block_size,
796 transport_sub_state |= StopPendingCapture;
797 pending_abort = abort;
801 if ((transport_sub_state & PendingDeclickOut) == 0) {
802 transport_sub_state |= PendingDeclickOut;
803 /* we'll be called again after the declick */
807 realtime_stop (abort);
808 schedule_butler_transport_work ();
812 Session::start_transport ()
814 _last_roll_location = _transport_frame;
816 /* if record status is Enabled, move it to Recording. if its
817 already Recording, move it to Disabled.
820 switch (record_status()) {
835 if (!synced_to_jack() || _exporting) {
836 actually_start_transport ();
838 waiting_to_start = true;
843 Session::actually_start_transport ()
845 waiting_to_start = false;
847 transport_sub_state |= PendingDeclickIn;
848 _transport_speed = 1.0;
850 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
851 (*i)->realtime_set_speed ((*i)->speed(), true);
854 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
856 TransportStateChange (); /* EMIT SIGNAL */
860 Session::post_transport ()
862 if (post_transport_work & PostTransportAudition) {
863 if (auditioner && auditioner->active()) {
864 process_function = &Session::process_audition;
866 process_function = &Session::process_with_events;
870 if (post_transport_work & PostTransportStop) {
872 transport_sub_state = 0;
875 if (post_transport_work & PostTransportLocate) {
877 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
882 transport_sub_state = 0;
888 post_transport_work = PostTransportWork (0);
892 Session::set_rf_speed (float speed)
895 cumulative_rf_motion = 0;
900 Session::reset_rf_scale (jack_nframes_t motion)
902 cumulative_rf_motion += motion;
904 if (cumulative_rf_motion < 4 * _current_frame_rate) {
906 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
908 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
920 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
922 bool reverse = false;
923 bool non_rt_required = false;
925 if (_transport_speed) {
926 error << _("please stop the transport before adjusting slave settings") << endmsg;
927 /* help out non-MVC friendly UI's by telling them the slave type changed */
928 ControlChanged (SlaveType); /* EMIT SIGNAL */
932 if (src == _slave_type) {
936 // if (src == JACK && Config->get_jack_time_master()) {
946 if (_transport_speed < 0.0) {
958 _slave = new MTC_Slave (*this, *_mtc_port);
961 catch (failed_constructor& err) {
966 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
969 _desired_transport_speed = _transport_speed;
973 _slave = new JACK_Slave (_engine.jack());
974 _desired_transport_speed = _transport_speed;
980 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
981 if (!(*i)->hidden()) {
982 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
983 non_rt_required = true;
985 (*i)->set_slaved (_slave);
990 reverse_diskstream_buffers ();
993 if (non_rt_required) {
994 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
995 schedule_butler_transport_work ();
999 ControlChanged (SlaveType); /* EMIT SIGNAL */
1005 Session::reverse_diskstream_buffers ()
1007 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1008 schedule_butler_transport_work ();
1012 Session::set_diskstream_speed (DiskStream* stream, float speed)
1014 if (stream->realtime_set_speed (speed, false)) {
1015 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1016 schedule_butler_transport_work ();
1022 Session::set_audio_range (list<AudioRange>& range)
1024 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1025 ev->audio_range = range;
1030 Session::request_play_range (bool yn)
1032 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1037 Session::set_play_range (bool yn)
1039 /* Called from event-processing context */
1041 if (_play_range != yn) {
1046 /* stop transport */
1047 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1051 ControlChanged (PlayRange); /* EMIT SIGNAL */
1056 Session::setup_auto_play ()
1058 /* Called from event-processing context */
1062 _clear_event_type (Event::RangeStop);
1063 _clear_event_type (Event::RangeLocate);
1069 list<AudioRange>::size_type sz = current_audio_range.size();
1073 list<AudioRange>::iterator i = current_audio_range.begin();
1074 list<AudioRange>::iterator next;
1076 while (i != current_audio_range.end()) {
1081 /* locating/stopping is subject to delays for declicking.
1084 jack_nframes_t requested_frame = (*i).end;
1086 if (requested_frame > current_block_size) {
1087 requested_frame -= current_block_size;
1089 requested_frame = 0;
1092 if (next == current_audio_range.end()) {
1093 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1095 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1103 } else if (sz == 1) {
1105 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1110 /* now start rolling at the right place */
1112 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1117 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1120 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1122 request_locate (start, true);
1126 Session::engine_halted ()
1128 /* there will be no more calls to process(), so
1129 we'd better clean up for ourselves, right now.
1131 but first, make sure the butler is out of
1135 atomic_set (&butler_should_do_transport_work, 0);
1136 post_transport_work = PostTransportWork (0);
1139 realtime_stop (false);
1140 non_realtime_stop (false);
1141 transport_sub_state = 0;
1143 TransportStateChange (); /* EMIT SIGNAL */
1148 Session::xrun_recovery ()
1150 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1152 HaltOnXrun (); /* EMIT SIGNAL */
1154 /* it didn't actually halt, but we need
1155 to handle things in the same way.
1163 Session::update_latency_compensation (bool with_stop, bool abort)
1165 bool update_jack = false;
1167 if (_state_of_the_state & Deletion) {
1171 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
1172 RWLockMonitor lm2 (diskstream_lock, false, __LINE__, __FILE__);
1173 _worst_track_latency = 0;
1175 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1177 (*i)->transport_stopped (abort, (post_transport_work & PostTransportLocate),
1178 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1181 jack_nframes_t old_latency = (*i)->signal_latency ();
1182 jack_nframes_t track_latency = (*i)->update_total_latency ();
1184 if (old_latency != track_latency) {
1188 if (!(*i)->hidden() && ((*i)->active())) {
1189 _worst_track_latency = max (_worst_track_latency, track_latency);
1193 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1194 (*i)->set_latency_delay (_worst_track_latency);
1197 /* tell JACK to play catch up */
1200 _engine.update_total_latencies ();
1203 set_worst_io_latencies (false);
1205 /* reflect any changes in latencies into capture offsets
1208 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1209 (*i)->set_capture_offset ();
1214 Session::update_latency_compensation_proxy (void* ignored)
1216 update_latency_compensation (false, false);