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 <glibmm/thread.h>
31 #include <pbd/pthread_utils.h>
32 #include <pbd/memento_command.h>
34 #include <midi++/mmc.h>
35 #include <midi++/port.h>
37 #include <ardour/ardour.h>
38 #include <ardour/audioengine.h>
39 #include <ardour/session.h>
40 #include <ardour/audio_diskstream.h>
41 #include <ardour/auditioner.h>
42 #include <ardour/slave.h>
43 #include <ardour/location.h>
48 using namespace ARDOUR;
53 Session::request_input_change_handling ()
55 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
60 Session::request_slave_source (SlaveSource src)
62 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, 0, 0.0);
65 /* could set_seamless_loop() be disposed of entirely?*/
66 Config->set_seamless_loop (false);
68 Config->set_seamless_loop (true);
75 Session::request_transport_speed (float speed)
77 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
82 Session::request_diskstream_speed (Diskstream& ds, float speed)
84 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
90 Session::request_stop (bool abort)
92 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
97 Session::request_locate (nframes_t target_frame, bool with_roll)
99 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
104 Session::force_locate (nframes_t target_frame, bool with_roll)
106 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
111 Session::request_play_loop (bool yn)
114 Location *location = _locations.auto_loop_location();
116 if (location == 0 && yn) {
117 error << _("Cannot loop - no loop range defined")
122 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
125 if (!yn && Config->get_seamless_loop() && transport_rolling()) {
126 // request an immediate locate to refresh the diskstreams
127 // after disabling looping
128 request_locate (_transport_frame-1, false);
133 Session::realtime_stop (bool abort)
135 /* assume that when we start, we'll be moving forwards */
137 // FIXME: where should this really be? [DR]
138 //send_full_time_code();
139 deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
140 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
142 if (_transport_speed < 0.0f) {
143 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
145 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
148 if (actively_recording()) {
150 /* move the transport position back to where the
151 request for a stop was noticed. we rolled
152 past that point to pick up delayed input.
155 #ifndef LEAVE_TRANSPORT_UNADJUSTED
156 decrement_transport_position (_worst_output_latency);
159 /* the duration change is not guaranteed to have happened, but is likely */
161 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
165 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
168 _clear_event_type (Event::StopOnce);
169 _clear_event_type (Event::RangeStop);
170 _clear_event_type (Event::RangeLocate);
172 disable_record (true);
174 reset_slave_state ();
176 _transport_speed = 0;
178 if (Config->get_use_video_sync()) {
179 waiting_for_sync_offset = true;
182 transport_sub_state = (Config->get_auto_return() ? AutoReturning : 0);
186 Session::butler_transport_work ()
188 boost::shared_ptr<RouteList> r = routes.reader ();
189 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
191 if (post_transport_work & PostTransportCurveRealloc) {
192 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
193 (*i)->curve_reallocate();
197 if (post_transport_work & PostTransportInputChange) {
198 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
199 (*i)->non_realtime_input_change ();
203 if (post_transport_work & PostTransportSpeed) {
204 non_realtime_set_speed ();
207 if (post_transport_work & PostTransportReverse) {
211 cumulative_rf_motion = 0;
214 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
215 if (!(*i)->hidden()) {
216 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
217 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
220 (*i)->seek (_transport_frame);
226 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
227 non_realtime_stop (post_transport_work & PostTransportAbort);
230 if (post_transport_work & PostTransportOverWrite) {
231 non_realtime_overwrite ();
234 if (post_transport_work & PostTransportAudition) {
235 non_realtime_set_audition ();
238 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
242 Session::non_realtime_set_speed ()
244 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
246 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
247 (*i)->non_realtime_set_speed ();
252 Session::non_realtime_overwrite ()
254 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
256 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
257 if ((*i)->pending_overwrite) {
258 (*i)->overwrite_existing_buffers ();
264 Session::non_realtime_stop (bool abort)
274 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
276 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
277 if ((*i)->get_captured_frames () != 0) {
283 /* stop and locate are merged here because they share a lot of common stuff */
286 now = localtime (&xnow);
289 auditioner->cancel_audition ();
293 cumulative_rf_motion = 0;
297 begin_reversible_command ("capture");
299 Location* loc = _locations.end_location();
300 bool change_end = false;
302 if (_transport_frame < loc->end()) {
304 /* stopped recording before current end */
306 if (_end_location_is_free) {
308 /* first capture for this session, move end back to where we are */
313 } else if (_transport_frame > loc->end()) {
315 /* stopped recording after the current end, extend it */
321 XMLNode &before = loc->get_state();
322 loc->set_end(_transport_frame);
323 XMLNode &after = loc->get_state();
324 add_command (new MementoCommand<Location>(*loc, &before, &after));
327 _end_location_is_free = false;
328 _have_captured = true;
331 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
332 (*i)->transport_stopped (*now, xnow, abort);
335 boost::shared_ptr<RouteList> r = routes.reader ();
337 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
338 if (!(*i)->hidden()) {
339 (*i)->set_pending_declick (0);
344 commit_reversible_command ();
347 if (_engine.running()) {
348 update_latency_compensation (true, abort);
351 if (Config->get_auto_return() || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
353 if (pending_locate_flush) {
354 flush_all_redirects ();
357 if ((Config->get_auto_return() || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
359 _transport_frame = last_stop_frame;
361 if (synced_to_jack()) {
362 _engine.transport_locate (_transport_frame);
366 #ifndef LEAVE_TRANSPORT_UNADJUSTED
370 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
371 if (!(*i)->hidden()) {
372 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
373 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
376 (*i)->seek (_transport_frame);
381 #ifdef LEAVE_TRANSPORT_UNADJUSTED
385 last_stop_frame = _transport_frame;
389 /* XXX its a little odd that we're doing this here
390 when realtime_stop(), which has already executed,
394 if (!Config->get_latched_record_enable()) {
395 g_atomic_int_set (&_record_status, Disabled);
397 g_atomic_int_set (&_record_status, Enabled);
399 RecordStateChanged (); /* emit signal */
402 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
403 /* capture start has been changed, so save pending state */
404 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 */
414 if (did_record && !saved) {
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) && Config->get_slave_source() == 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_play_loop (bool yn)
467 /* Called from event-handling context */
469 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
475 if (yn && Config->get_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 ((play_loop = yn)) {
488 if ((loc = _locations.auto_loop_location()) != 0) {
490 if (Config->get_seamless_loop()) {
491 // set all diskstreams to use internal looping
492 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
493 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
494 if (!(*i)->hidden()) {
495 (*i)->set_loop (loc);
500 // set all diskstreams to NOT use internal looping
501 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
502 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
503 if (!(*i)->hidden()) {
509 /* stick in the loop event */
511 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
514 /* locate to start of loop and roll if current pos is outside of the loop range */
515 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
516 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
520 // locate to current position (+ 1 to force reload)
521 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
529 clear_events (Event::AutoLoop);
531 // set all diskstreams to NOT use internal looping
532 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
533 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
534 if (!(*i)->hidden()) {
543 Session::flush_all_redirects ()
545 boost::shared_ptr<RouteList> r = routes.reader ();
547 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
548 (*i)->flush_redirects ();
553 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
555 if (synced_to_jack()) {
560 _slave->speed_and_position (sp, pos);
562 if (target_frame != pos) {
564 /* tell JACK to change transport position, and we will
565 follow along later in ::follow_slave()
568 _engine.transport_locate (target_frame);
570 if (sp != 1.0f && with_roll) {
571 _engine.transport_start ();
578 locate (target_frame, with_roll, with_flush, with_loop);
583 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
585 if (actively_recording()) {
589 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
591 set_transport_speed (1.0, false);
593 loop_changing = false;
598 // [DR] FIXME: find out exactly where this should go below
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;
604 if (_transport_speed && (!with_loop || loop_changing)) {
605 /* schedule a declick. we'll be called again when its done */
607 if (!(transport_sub_state & PendingDeclickOut)) {
608 transport_sub_state |= (PendingDeclickOut|PendingLocate);
609 pending_locate_frame = target_frame;
610 pending_locate_roll = with_roll;
611 pending_locate_flush = with_flush;
616 if (transport_rolling() && !Config->get_auto_play() && !with_roll && !(synced_to_jack() && play_loop)) {
617 realtime_stop (false);
620 if ( !with_loop || loop_changing) {
622 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
625 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
628 schedule_butler_transport_work ();
632 /* this is functionally what clear_clicks() does but with a tentative lock */
634 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
636 if (clickm.locked()) {
638 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
647 /* switch from input if we're going to roll */
648 if (Config->get_monitoring_model() == HardwareMonitoring) {
650 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
652 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
653 if ((*i)->record_enabled ()) {
654 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
655 (*i)->monitor_input (!Config->get_auto_input());
660 /* otherwise we're going to stop, so do the opposite */
661 if (Config->get_monitoring_model() == HardwareMonitoring) {
662 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
664 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
665 if ((*i)->record_enabled ()) {
666 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
667 (*i)->monitor_input (true);
673 /* cancel looped playback if transport pos outside of loop range */
675 Location* al = _locations.auto_loop_location();
677 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
678 // cancel looping directly, this is called from event handling context
679 set_play_loop (false);
683 loop_changing = false;
685 _send_smpte_update = true;
689 Session::set_transport_speed (float speed, bool abort)
691 if (_transport_speed == speed) {
696 speed = min (8.0f, speed);
697 } else if (speed < 0) {
698 speed = max (-8.0f, speed);
701 if (transport_rolling() && speed == 0.0) {
703 if (Config->get_monitoring_model() == HardwareMonitoring)
705 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
707 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
708 if ((*i)->record_enabled ()) {
709 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
710 (*i)->monitor_input (true);
715 if (synced_to_jack ()) {
716 _engine.transport_stop ();
718 stop_transport (abort);
721 } else if (transport_stopped() && speed == 1.0) {
723 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
727 if (Config->get_monitoring_model() == HardwareMonitoring) {
729 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
731 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
732 if (Config->get_auto_input() && (*i)->record_enabled ()) {
733 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
734 (*i)->monitor_input (false);
739 if (synced_to_jack()) {
740 _engine.transport_start ();
747 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
751 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
752 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
757 if (actively_recording()) {
761 if (speed > 0.0f && _transport_frame == current_end_frame()) {
765 if (speed < 0.0f && _transport_frame == 0) {
771 /* if we are reversing relative to the current speed, or relative to the speed
772 before the last stop, then we have to do extra work.
775 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
776 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
779 _last_transport_speed = _transport_speed;
780 _transport_speed = speed;
782 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
783 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
784 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
785 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
789 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
790 schedule_butler_transport_work ();
796 Session::stop_transport (bool abort)
798 if (_transport_speed == 0.0f) {
802 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
803 _worst_output_latency > current_block_size)
806 /* we need to capture the audio that has still not yet been received by the system
807 at the time the stop is requested, so we have to roll past that time.
809 we want to declick before stopping, so schedule the autostop for one
810 block before the actual end. we'll declick in the subsequent block,
811 and then we'll really be stopped.
814 Event *ev = new Event (Event::StopOnce, Event::Replace,
815 _transport_frame + _worst_output_latency - current_block_size,
819 transport_sub_state |= StopPendingCapture;
820 pending_abort = abort;
825 if ((transport_sub_state & PendingDeclickOut) == 0) {
826 transport_sub_state |= PendingDeclickOut;
827 /* we'll be called again after the declick */
828 pending_abort = abort;
832 realtime_stop (abort);
833 schedule_butler_transport_work ();
837 Session::start_transport ()
839 _last_roll_location = _transport_frame;
841 /* if record status is Enabled, move it to Recording. if its
842 already Recording, move it to Disabled.
845 switch (record_status()) {
847 if (!Config->get_punch_in()) {
853 disable_record (false);
860 if (!synced_to_jack() || _exporting) {
861 actually_start_transport ();
863 waiting_to_start = true;
868 Session::actually_start_transport ()
870 waiting_to_start = false;
872 transport_sub_state |= PendingDeclickIn;
873 _transport_speed = 1.0;
875 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
876 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
877 (*i)->realtime_set_speed ((*i)->speed(), true);
880 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
882 TransportStateChange (); /* EMIT SIGNAL */
885 /** Do any transport work in the audio thread that needs to be done after the
886 * transport thread is finished. Audio thread, realtime safe.
889 Session::post_transport ()
891 if (post_transport_work & PostTransportAudition) {
892 if (auditioner && auditioner->active()) {
893 process_function = &Session::process_audition;
895 process_function = &Session::process_with_events;
899 if (post_transport_work & PostTransportStop) {
901 transport_sub_state = 0;
904 if (post_transport_work & PostTransportLocate) {
906 if ((Config->get_auto_play() && !_exporting) || (post_transport_work & PostTransportRoll)) {
911 transport_sub_state = 0;
917 post_transport_work = PostTransportWork (0);
921 Session::reset_rf_scale (nframes_t motion)
923 cumulative_rf_motion += motion;
925 if (cumulative_rf_motion < 4 * _current_frame_rate) {
927 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
929 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
941 Session::set_slave_source (SlaveSource src)
943 bool reverse = false;
944 bool non_rt_required = false;
946 if (_transport_speed) {
947 error << _("please stop the transport before adjusting slave settings") << endmsg;
951 // 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;
992 Config->set_slave_source (src);
994 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
995 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
996 if (!(*i)->hidden()) {
997 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
998 non_rt_required = true;
1000 (*i)->set_slaved (_slave);
1005 reverse_diskstream_buffers ();
1008 if (non_rt_required) {
1009 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1010 schedule_butler_transport_work ();
1017 Session::reverse_diskstream_buffers ()
1019 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1020 schedule_butler_transport_work ();
1024 Session::set_diskstream_speed (Diskstream* stream, float speed)
1026 if (stream->realtime_set_speed (speed, false)) {
1027 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1028 schedule_butler_transport_work ();
1034 Session::set_audio_range (list<AudioRange>& range)
1036 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1037 ev->audio_range = range;
1042 Session::request_play_range (bool yn)
1044 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1049 Session::set_play_range (bool yn)
1051 /* Called from event-processing context */
1053 if (_play_range != yn) {
1058 /* stop transport */
1059 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
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 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 (nframes_t start, 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 g_atomic_int_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 _worst_track_latency = 0;
1183 boost::shared_ptr<RouteList> r = routes.reader ();
1185 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1187 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1188 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1191 nframes_t old_latency = (*i)->signal_latency ();
1192 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 = r->begin(); i != r->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 ();
1215 /* reflect any changes in latencies into capture offsets
1218 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1220 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1221 (*i)->set_capture_offset ();
1226 Session::update_latency_compensation_proxy (void* ignored)
1228 update_latency_compensation (false, false);