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, jack_nframes_t pos)
62 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, pos, 0.0);
64 if (src == Session::JACK) {
65 /* could set_seamless_loop() be disposed of entirely?*/
66 set_seamless_loop (false);
69 set_seamless_loop (true);
76 Session::request_transport_speed (float speed)
78 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
83 Session::request_diskstream_speed (Diskstream& ds, float speed)
85 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
91 Session::request_stop (bool abort)
93 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
98 Session::request_locate (jack_nframes_t target_frame, bool with_roll)
100 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
105 Session::force_locate (jack_nframes_t target_frame, bool with_roll)
107 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
112 Session::request_auto_loop (bool yn)
115 Location *location = _locations.auto_loop_location();
117 if (location == 0 && yn) {
118 error << _("Cannot loop - no loop range defined")
123 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
126 if (!yn && seamless_loop && transport_rolling()) {
127 // request an immediate locate to refresh the diskstreams
128 // after disabling looping
129 request_locate (_transport_frame-1, true);
134 Session::set_seamless_loop (bool yn)
136 if (seamless_loop != yn) {
139 if (auto_loop && transport_rolling()) {
140 // to reset diskstreams etc
141 request_auto_loop (true);
144 ControlChanged (SeamlessLoop); /* EMIT */
149 Session::realtime_stop (bool abort)
151 /* assume that when we start, we'll be moving forwards */
153 if (_transport_speed < 0.0f) {
154 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
156 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
159 if (actively_recording()) {
161 /* move the transport position back to where the
162 request for a stop was noticed. we rolled
163 past that point to pick up delayed input.
166 #ifndef LEAVE_TRANSPORT_UNADJUSTED
167 decrement_transport_position (_worst_output_latency);
170 /* the duration change is not guaranteed to have happened, but is likely */
172 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
176 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
179 _clear_event_type (Event::StopOnce);
180 _clear_event_type (Event::RangeStop);
181 _clear_event_type (Event::RangeLocate);
183 disable_record (true);
185 reset_slave_state ();
187 _transport_speed = 0;
189 transport_sub_state = (auto_return ? AutoReturning : 0);
193 Session::butler_transport_work ()
195 Glib::RWLock::ReaderLock dsm (diskstream_lock);
196 boost::shared_ptr<RouteList> r = routes.reader ();
198 if (post_transport_work & PostTransportCurveRealloc) {
199 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
200 (*i)->curve_reallocate();
204 if (post_transport_work & PostTransportInputChange) {
205 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
206 (*i)->non_realtime_input_change ();
210 if (post_transport_work & PostTransportSpeed) {
211 non_realtime_set_speed ();
214 if (post_transport_work & PostTransportReverse) {
218 cumulative_rf_motion = 0;
221 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
222 if (!(*i)->hidden()) {
223 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
224 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
227 (*i)->seek (_transport_frame);
233 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
234 non_realtime_stop (post_transport_work & PostTransportAbort);
237 if (post_transport_work & PostTransportOverWrite) {
238 non_realtime_overwrite ();
241 if (post_transport_work & PostTransportAudition) {
242 non_realtime_set_audition ();
245 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
249 Session::non_realtime_set_speed ()
251 Glib::RWLock::ReaderLock lm (diskstream_lock);
253 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
254 (*i)->non_realtime_set_speed ();
259 Session::non_realtime_overwrite ()
261 Glib::RWLock::ReaderLock lm (diskstream_lock);
263 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
264 if ((*i)->pending_overwrite) {
265 (*i)->overwrite_existing_buffers ();
271 Session::non_realtime_stop (bool abort)
279 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
280 if ((*i)->get_captured_frames () != 0) {
286 /* stop and locate are merged here because they share a lot of common stuff */
289 now = localtime (&xnow);
292 auditioner->cancel_audition ();
296 cumulative_rf_motion = 0;
300 begin_reversible_command ("capture");
302 Location* loc = _locations.end_location();
303 bool change_end = false;
305 if (_transport_frame < loc->end()) {
307 /* stopped recording before current end */
309 if (_end_location_is_free) {
311 /* first capture for this session, move end back to where we are */
316 } else if (_transport_frame > loc->end()) {
318 /* stopped recording after the current end, extend it */
324 XMLNode &before = loc->get_state();
325 loc->set_end(_transport_frame);
326 XMLNode &after = loc->get_state();
327 add_command (new MementoCommand<Location>(*loc, before, after));
330 _end_location_is_free = false;
331 _have_captured = true;
334 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
335 (*i)->transport_stopped (*now, xnow, abort);
338 boost::shared_ptr<RouteList> r = routes.reader ();
340 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
341 if (!(*i)->hidden()) {
342 (*i)->set_pending_declick (0);
347 commit_reversible_command ();
350 if (_engine.running()) {
351 update_latency_compensation (true, abort);
354 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
356 if (pending_locate_flush) {
357 flush_all_redirects ();
360 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
362 _transport_frame = last_stop_frame;
364 if (synced_to_jack()) {
365 _engine.transport_locate (_transport_frame);
369 #ifndef LEAVE_TRANSPORT_UNADJUSTED
373 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
374 if (!(*i)->hidden()) {
375 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
376 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
379 (*i)->seek (_transport_frame);
384 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
386 #ifdef LEAVE_TRANSPORT_UNADJUSTED
390 last_stop_frame = _transport_frame;
392 send_full_time_code ();
393 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
394 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
398 /* XXX its a little odd that we're doing this here
399 when realtime_stop(), which has already executed,
403 if (!Config->get_latched_record_enable()) {
404 g_atomic_int_set (&_record_status, Disabled);
406 g_atomic_int_set (&_record_status, Enabled);
408 RecordStateChanged (); /* emit signal */
411 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
412 /* capture start has been changed, so save pending state */
413 save_state ("", true);
417 /* always try to get rid of this */
419 remove_pending_capture_state ();
421 /* save the current state of things if appropriate */
424 save_state (_current_snapshot_name);
427 if (post_transport_work & PostTransportDuration) {
428 DurationChanged (); /* EMIT SIGNAL */
431 if (post_transport_work & PostTransportStop) {
434 /* do not turn off autoloop on stop */
438 PositionChanged (_transport_frame); /* EMIT SIGNAL */
439 TransportStateChange (); /* EMIT SIGNAL */
441 /* and start it up again if relevant */
443 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
444 request_transport_speed (1.0);
445 pending_locate_roll = false;
450 Session::check_declick_out ()
452 bool locate_required = transport_sub_state & PendingLocate;
454 /* this is called after a process() iteration. if PendingDeclickOut was set,
455 it means that we were waiting to declick the output (which has just been
456 done) before doing something else. this is where we do that "something else".
458 note: called from the audio thread.
461 if (transport_sub_state & PendingDeclickOut) {
463 if (locate_required) {
464 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
465 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
467 stop_transport (pending_abort);
468 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
474 Session::set_auto_loop (bool yn)
476 /* Called from event-handling context */
478 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
484 if (yn && seamless_loop && synced_to_jack()) {
485 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
486 "Recommend changing the configured options")
492 if ((auto_loop = yn)) {
497 if ((loc = _locations.auto_loop_location()) != 0) {
500 // set all diskstreams to use internal looping
501 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
502 if (!(*i)->hidden()) {
503 (*i)->set_loop (loc);
508 // set all diskstreams to NOT use internal looping
509 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
510 if (!(*i)->hidden()) {
516 /* stick in the loop event */
518 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
521 /* locate to start of loop and roll if current pos is outside of the loop range */
522 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
523 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
527 // locate to current position (+ 1 to force reload)
528 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
536 clear_events (Event::AutoLoop);
538 // set all diskstreams to NOT use internal looping
539 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
540 if (!(*i)->hidden()) {
547 ControlChanged (AutoLoop); /* EMIT SIGNAL */
551 Session::flush_all_redirects ()
553 boost::shared_ptr<RouteList> r = routes.reader ();
555 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
556 (*i)->flush_redirects ();
561 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
563 if (synced_to_jack()) {
568 _slave->speed_and_position (sp, pos);
570 if (target_frame != pos) {
572 /* tell JACK to change transport position, and we will
573 follow along later in ::follow_slave()
576 _engine.transport_locate (target_frame);
578 if (sp != 1.0f && with_roll) {
579 _engine.transport_start ();
586 locate (target_frame, with_roll, with_flush, with_loop);
591 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
593 if (actively_recording()) {
597 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
599 set_transport_speed (1.0, false);
601 loop_changing = false;
605 _transport_frame = target_frame;
607 if (_transport_speed && (!with_loop || loop_changing)) {
608 /* schedule a declick. we'll be called again when its done */
610 if (!(transport_sub_state & PendingDeclickOut)) {
611 transport_sub_state |= (PendingDeclickOut|PendingLocate);
612 pending_locate_frame = target_frame;
613 pending_locate_roll = with_roll;
614 pending_locate_flush = with_flush;
619 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
620 realtime_stop (false);
623 if ( !with_loop || loop_changing) {
625 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
628 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
631 schedule_butler_transport_work ();
635 /* this is functionally what clear_clicks() does but with a tentative lock */
637 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
639 if (clickm.locked()) {
641 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
650 /* switch from input if we're going to roll */
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 Glib::RWLock::ReaderLock dsm (diskstream_lock);
657 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
658 if ((*i)->record_enabled ()) {
659 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
660 (*i)->monitor_input (!auto_input);
665 /* otherwise we're going to stop, so do the opposite */
666 if (Config->get_use_hardware_monitoring()) {
667 /* Even though this is called from RT context we are using
668 a non-tentative rwlock here, because the action must occur.
669 The rarity and short potential lock duration makes this "OK"
671 Glib::RWLock::ReaderLock dsm (diskstream_lock);
672 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
673 if ((*i)->record_enabled ()) {
674 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
675 (*i)->monitor_input (true);
681 /* cancel autoloop if transport pos outside of loop range */
683 Location* al = _locations.auto_loop_location();
685 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
686 // cancel looping directly, this is called from event handling context
687 set_auto_loop(false);
691 loop_changing = false;
695 Session::set_transport_speed (float speed, bool abort)
697 if (_transport_speed == speed) {
702 speed = min (8.0f, speed);
703 } else if (speed < 0) {
704 speed = max (-8.0f, speed);
707 if (transport_rolling() && speed == 0.0) {
709 if (Config->get_use_hardware_monitoring())
711 /* Even though this is called from RT context we are using
712 a non-tentative rwlock here, because the action must occur.
713 The rarity and short potential lock duration makes this "OK"
715 Glib::RWLock::ReaderLock dsm (diskstream_lock);
716 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
717 if ((*i)->record_enabled ()) {
718 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
719 (*i)->monitor_input (true);
724 if (synced_to_jack ()) {
725 _engine.transport_stop ();
727 stop_transport (abort);
730 } else if (transport_stopped() && speed == 1.0) {
732 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
736 if (Config->get_use_hardware_monitoring()) {
737 /* Even though this is called from RT context we are using
738 a non-tentative rwlock here, because the action must occur.
739 The rarity and short potential lock duration makes this "OK"
741 Glib::RWLock::ReaderLock dsm (diskstream_lock);
742 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
743 if (auto_input && (*i)->record_enabled ()) {
744 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
745 (*i)->monitor_input (false);
750 if (synced_to_jack()) {
751 _engine.transport_start ();
758 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
762 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
763 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
768 if (actively_recording()) {
772 if (speed > 0.0f && _transport_frame == current_end_frame()) {
776 if (speed < 0.0f && _transport_frame == 0) {
782 /* if we are reversing relative to the current speed, or relative to the speed
783 before the last stop, then we have to do extra work.
786 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
787 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
790 _last_transport_speed = _transport_speed;
791 _transport_speed = speed;
793 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
794 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
795 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
799 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
800 schedule_butler_transport_work ();
806 Session::stop_transport (bool abort)
808 if (_transport_speed == 0.0f) {
812 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
813 _worst_output_latency > current_block_size)
816 /* we need to capture the audio that has still not yet been received by the system
817 at the time the stop is requested, so we have to roll past that time.
819 we want to declick before stopping, so schedule the autostop for one
820 block before the actual end. we'll declick in the subsequent block,
821 and then we'll really be stopped.
824 Event *ev = new Event (Event::StopOnce, Event::Replace,
825 _transport_frame + _worst_output_latency - current_block_size,
829 transport_sub_state |= StopPendingCapture;
830 pending_abort = abort;
834 if ((transport_sub_state & PendingDeclickOut) == 0) {
835 transport_sub_state |= PendingDeclickOut;
836 /* we'll be called again after the declick */
840 realtime_stop (abort);
841 schedule_butler_transport_work ();
845 Session::start_transport ()
847 _last_roll_location = _transport_frame;
849 /* if record status is Enabled, move it to Recording. if its
850 already Recording, move it to Disabled.
853 switch (record_status()) {
861 disable_record (false);
868 if (!synced_to_jack() || _exporting) {
869 actually_start_transport ();
871 waiting_to_start = true;
876 Session::actually_start_transport ()
878 waiting_to_start = false;
880 transport_sub_state |= PendingDeclickIn;
881 _transport_speed = 1.0;
883 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
884 (*i)->realtime_set_speed ((*i)->speed(), true);
887 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
889 TransportStateChange (); /* EMIT SIGNAL */
893 Session::post_transport ()
895 if (post_transport_work & PostTransportAudition) {
896 if (auditioner && auditioner->active()) {
897 process_function = &Session::process_audition;
899 process_function = &Session::process_with_events;
903 if (post_transport_work & PostTransportStop) {
905 transport_sub_state = 0;
908 if (post_transport_work & PostTransportLocate) {
910 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
915 transport_sub_state = 0;
921 post_transport_work = PostTransportWork (0);
925 Session::set_rf_speed (float speed)
928 cumulative_rf_motion = 0;
933 Session::reset_rf_scale (jack_nframes_t motion)
935 cumulative_rf_motion += motion;
937 if (cumulative_rf_motion < 4 * _current_frame_rate) {
939 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
941 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
953 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
955 bool reverse = false;
956 bool non_rt_required = false;
958 if (src == _slave_type) {
962 if (_transport_speed) {
963 error << _("please stop the transport before adjusting slave settings") << endmsg;
964 /* help out non-MVC friendly UI's by telling them the slave type changed */
965 ControlChanged (SlaveType); /* EMIT SIGNAL */
969 // if (src == JACK && Config->get_jack_time_master()) {
979 if (_transport_speed < 0.0) {
991 _slave = new MTC_Slave (*this, *_mtc_port);
994 catch (failed_constructor& err) {
999 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1002 _desired_transport_speed = _transport_speed;
1006 _slave = new JACK_Slave (_engine.jack());
1007 _desired_transport_speed = _transport_speed;
1013 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1014 if (!(*i)->hidden()) {
1015 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1016 non_rt_required = true;
1018 (*i)->set_slaved (_slave);
1023 reverse_diskstream_buffers ();
1026 if (non_rt_required) {
1027 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1028 schedule_butler_transport_work ();
1032 ControlChanged (SlaveType); /* EMIT SIGNAL */
1038 Session::reverse_diskstream_buffers ()
1040 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1041 schedule_butler_transport_work ();
1045 Session::set_diskstream_speed (Diskstream* stream, float speed)
1047 if (stream->realtime_set_speed (speed, false)) {
1048 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1049 schedule_butler_transport_work ();
1055 Session::set_audio_range (list<AudioRange>& range)
1057 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1058 ev->audio_range = range;
1063 Session::request_play_range (bool yn)
1065 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1070 Session::set_play_range (bool yn)
1072 /* Called from event-processing context */
1074 if (_play_range != yn) {
1079 /* stop transport */
1080 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1084 ControlChanged (PlayRange); /* EMIT SIGNAL */
1089 Session::setup_auto_play ()
1091 /* Called from event-processing context */
1095 _clear_event_type (Event::RangeStop);
1096 _clear_event_type (Event::RangeLocate);
1102 list<AudioRange>::size_type sz = current_audio_range.size();
1106 list<AudioRange>::iterator i = current_audio_range.begin();
1107 list<AudioRange>::iterator next;
1109 while (i != current_audio_range.end()) {
1114 /* locating/stopping is subject to delays for declicking.
1117 jack_nframes_t requested_frame = (*i).end;
1119 if (requested_frame > current_block_size) {
1120 requested_frame -= current_block_size;
1122 requested_frame = 0;
1125 if (next == current_audio_range.end()) {
1126 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1128 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1136 } else if (sz == 1) {
1138 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1143 /* now start rolling at the right place */
1145 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1150 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1153 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1155 request_locate (start, true);
1159 Session::engine_halted ()
1161 /* there will be no more calls to process(), so
1162 we'd better clean up for ourselves, right now.
1164 but first, make sure the butler is out of
1168 g_atomic_int_set (&butler_should_do_transport_work, 0);
1169 post_transport_work = PostTransportWork (0);
1172 realtime_stop (false);
1173 non_realtime_stop (false);
1174 transport_sub_state = 0;
1176 TransportStateChange (); /* EMIT SIGNAL */
1181 Session::xrun_recovery ()
1183 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1185 HaltOnXrun (); /* EMIT SIGNAL */
1187 /* it didn't actually halt, but we need
1188 to handle things in the same way.
1196 Session::update_latency_compensation (bool with_stop, bool abort)
1198 bool update_jack = false;
1200 if (_state_of_the_state & Deletion) {
1204 Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1205 _worst_track_latency = 0;
1207 boost::shared_ptr<RouteList> r = routes.reader ();
1209 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1211 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1212 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1215 jack_nframes_t old_latency = (*i)->signal_latency ();
1216 jack_nframes_t track_latency = (*i)->update_total_latency ();
1218 if (old_latency != track_latency) {
1222 if (!(*i)->hidden() && ((*i)->active())) {
1223 _worst_track_latency = max (_worst_track_latency, track_latency);
1227 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1228 (*i)->set_latency_delay (_worst_track_latency);
1231 /* tell JACK to play catch up */
1234 _engine.update_total_latencies ();
1237 set_worst_io_latencies ();
1239 /* reflect any changes in latencies into capture offsets
1242 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1243 (*i)->set_capture_offset ();
1248 Session::update_latency_compensation_proxy (void* ignored)
1250 update_latency_compensation (false, false);