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>
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/audio_diskstream.h>
40 #include <ardour/auditioner.h>
41 #include <ardour/slave.h>
42 #include <ardour/location.h>
47 using namespace ARDOUR;
52 Session::request_input_change_handling ()
54 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
59 Session::request_slave_source (SlaveSource src, jack_nframes_t pos)
61 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, pos, 0.0);
63 if (src == Session::JACK) {
64 /* could set_seamless_loop() be disposed of entirely?*/
65 set_seamless_loop (false);
68 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 (AudioDiskstream& 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 (jack_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 (jack_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_auto_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 && seamless_loop && transport_rolling()) {
126 // request an immediate locate to refresh the diskstreams
127 // after disabling looping
128 request_locate (_transport_frame-1, true);
133 Session::set_seamless_loop (bool yn)
135 if (seamless_loop != yn) {
138 if (auto_loop && transport_rolling()) {
139 // to reset diskstreams etc
140 request_auto_loop (true);
143 ControlChanged (SeamlessLoop); /* EMIT */
148 Session::realtime_stop (bool abort)
150 /* assume that when we start, we'll be moving forwards */
152 if (_transport_speed < 0.0f) {
153 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
155 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
158 if (actively_recording()) {
160 /* move the transport position back to where the
161 request for a stop was noticed. we rolled
162 past that point to pick up delayed input.
165 #ifndef LEAVE_TRANSPORT_UNADJUSTED
166 decrement_transport_position (_worst_output_latency);
169 /* the duration change is not guaranteed to have happened, but is likely */
171 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
175 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
178 _clear_event_type (Event::StopOnce);
179 _clear_event_type (Event::RangeStop);
180 _clear_event_type (Event::RangeLocate);
182 disable_record (true);
184 reset_slave_state ();
186 _transport_speed = 0;
188 transport_sub_state = (auto_return ? AutoReturning : 0);
192 Session::butler_transport_work ()
194 Glib::RWLock::ReaderLock rm (route_lock);
195 Glib::RWLock::ReaderLock dsm (diskstream_lock);
197 if (post_transport_work & PostTransportCurveRealloc) {
198 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
199 (*i)->curve_reallocate();
203 if (post_transport_work & PostTransportInputChange) {
204 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
205 (*i)->non_realtime_input_change ();
209 if (post_transport_work & PostTransportSpeed) {
210 non_realtime_set_speed ();
213 if (post_transport_work & PostTransportReverse) {
217 cumulative_rf_motion = 0;
220 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
221 if (!(*i)->hidden()) {
222 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
223 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
226 (*i)->seek (_transport_frame);
232 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
233 non_realtime_stop (post_transport_work & PostTransportAbort);
236 if (post_transport_work & PostTransportOverWrite) {
237 non_realtime_overwrite ();
240 if (post_transport_work & PostTransportAudition) {
241 non_realtime_set_audition ();
244 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
248 Session::non_realtime_set_speed ()
250 Glib::RWLock::ReaderLock lm (diskstream_lock);
252 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
253 (*i)->non_realtime_set_speed ();
258 Session::non_realtime_overwrite ()
260 Glib::RWLock::ReaderLock lm (diskstream_lock);
262 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
263 if ((*i)->pending_overwrite) {
264 (*i)->overwrite_existing_buffers ();
270 Session::non_realtime_stop (bool abort)
278 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
279 if ((*i)->get_captured_frames () != 0) {
285 /* stop and locate are merged here because they share a lot of common stuff */
288 now = localtime (&xnow);
291 auditioner->cancel_audition ();
295 cumulative_rf_motion = 0;
299 begin_reversible_command ("capture");
301 Location* loc = _locations.end_location();
302 bool change_end = false;
304 if (_transport_frame < loc->end()) {
306 /* stopped recording before current end */
308 if (_end_location_is_free) {
310 /* first capture for this session, move end back to where we are */
315 } else if (_transport_frame > loc->end()) {
317 /* stopped recording after the current end, extend it */
323 XMLNode &before = loc->get_state();
324 loc->set_end(_transport_frame);
325 XMLNode &after = loc->get_state();
326 add_command (MementoCommand<Location>(*loc, before, after));
329 _end_location_is_free = false;
330 _have_captured = true;
333 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
334 (*i)->transport_stopped (*now, xnow, abort);
337 for (RouteList::iterator i = routes.begin(); i != routes.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 (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
353 if (pending_locate_flush) {
354 flush_all_redirects ();
357 if ((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 (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
371 if (!(*i)->hidden()) {
372 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
373 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
376 (*i)->seek (_transport_frame);
381 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
383 #ifdef LEAVE_TRANSPORT_UNADJUSTED
387 last_stop_frame = _transport_frame;
389 send_full_time_code ();
390 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
391 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
395 /* XXX its a little odd that we're doing this here
396 when realtime_stop(), which has already executed,
400 if (!Config->get_latched_record_enable()) {
401 g_atomic_int_set (&_record_status, Disabled);
403 g_atomic_int_set (&_record_status, Enabled);
405 RecordStateChanged (); /* emit signal */
408 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
409 /* capture start has been changed, so save pending state */
410 save_state ("", true);
413 /* always try to get rid of this */
415 remove_pending_capture_state ();
417 /* save the current state of things if appropriate */
420 save_state (_current_snapshot_name);
423 if (post_transport_work & PostTransportDuration) {
424 DurationChanged (); /* EMIT SIGNAL */
427 if (post_transport_work & PostTransportStop) {
430 /* do not turn off autoloop on stop */
434 PositionChanged (_transport_frame); /* EMIT SIGNAL */
435 TransportStateChange (); /* EMIT SIGNAL */
437 /* and start it up again if relevant */
439 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
440 request_transport_speed (1.0);
441 pending_locate_roll = false;
446 Session::check_declick_out ()
448 bool locate_required = transport_sub_state & PendingLocate;
450 /* this is called after a process() iteration. if PendingDeclickOut was set,
451 it means that we were waiting to declick the output (which has just been
452 done) before doing something else. this is where we do that "something else".
454 note: called from the audio thread.
457 if (transport_sub_state & PendingDeclickOut) {
459 if (locate_required) {
460 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
461 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
463 stop_transport (pending_abort);
464 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
470 Session::set_auto_loop (bool yn)
472 /* Called from event-handling context */
474 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
480 if (yn && seamless_loop && synced_to_jack()) {
481 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
482 "Recommend changing the configured options")
488 if ((auto_loop = yn)) {
493 if ((loc = _locations.auto_loop_location()) != 0) {
496 // set all diskstreams to use internal looping
497 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
498 if (!(*i)->hidden()) {
499 (*i)->set_loop (loc);
504 // set all diskstreams to NOT use internal looping
505 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
506 if (!(*i)->hidden()) {
512 /* stick in the loop event */
514 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
517 /* locate to start of loop and roll if current pos is outside of the loop range */
518 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
519 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
523 // locate to current position (+ 1 to force reload)
524 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
532 clear_events (Event::AutoLoop);
534 // set all diskstreams to NOT use internal looping
535 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
536 if (!(*i)->hidden()) {
543 ControlChanged (AutoLoop); /* EMIT SIGNAL */
547 Session::flush_all_redirects ()
549 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
550 (*i)->flush_redirects ();
555 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
557 if (synced_to_jack()) {
562 _slave->speed_and_position (sp, pos);
564 if (target_frame != pos) {
566 /* tell JACK to change transport position, and we will
567 follow along later in ::follow_slave()
570 _engine.transport_locate (target_frame);
572 if (sp != 1.0f && with_roll) {
573 _engine.transport_start ();
580 locate (target_frame, with_roll, with_flush, with_loop);
585 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
587 if (actively_recording()) {
591 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
593 set_transport_speed (1.0, false);
595 loop_changing = false;
599 _transport_frame = target_frame;
601 if (_transport_speed && (!with_loop || loop_changing)) {
602 /* schedule a declick. we'll be called again when its done */
604 if (!(transport_sub_state & PendingDeclickOut)) {
605 transport_sub_state |= (PendingDeclickOut|PendingLocate);
606 pending_locate_frame = target_frame;
607 pending_locate_roll = with_roll;
608 pending_locate_flush = with_flush;
613 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
614 realtime_stop (false);
617 if ( !with_loop || loop_changing) {
619 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
622 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
625 schedule_butler_transport_work ();
629 /* this is functionally what clear_clicks() does but with a tentative lock */
631 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
633 if (clickm.locked()) {
635 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
644 /* switch from input if we're going to roll */
645 if (Config->get_use_hardware_monitoring()) {
646 /* Even though this is called from RT context we are using
647 a non-tentative rwlock here, because the action must occur.
648 The rarity and short potential lock duration makes this "OK"
650 Glib::RWLock::ReaderLock dsm (diskstream_lock);
651 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
652 if ((*i)->record_enabled ()) {
653 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
654 (*i)->monitor_input (!auto_input);
659 /* otherwise we're going to stop, so do the opposite */
660 if (Config->get_use_hardware_monitoring()) {
661 /* Even though this is called from RT context we are using
662 a non-tentative rwlock here, because the action must occur.
663 The rarity and short potential lock duration makes this "OK"
665 Glib::RWLock::ReaderLock dsm (diskstream_lock);
666 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
667 if ((*i)->record_enabled ()) {
668 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
669 (*i)->monitor_input (true);
675 /* cancel autoloop if transport pos outside of loop range */
677 Location* al = _locations.auto_loop_location();
679 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
680 // cancel looping directly, this is called from event handling context
681 set_auto_loop(false);
685 loop_changing = false;
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_use_hardware_monitoring())
705 /* Even though this is called from RT context we are using
706 a non-tentative rwlock here, because the action must occur.
707 The rarity and short potential lock duration makes this "OK"
709 Glib::RWLock::ReaderLock dsm (diskstream_lock);
710 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
711 if ((*i)->record_enabled ()) {
712 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
713 (*i)->monitor_input (true);
718 if (synced_to_jack ()) {
719 _engine.transport_stop ();
721 stop_transport (abort);
724 } else if (transport_stopped() && speed == 1.0) {
726 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
730 if (Config->get_use_hardware_monitoring()) {
731 /* Even though this is called from RT context we are using
732 a non-tentative rwlock here, because the action must occur.
733 The rarity and short potential lock duration makes this "OK"
735 Glib::RWLock::ReaderLock dsm (diskstream_lock);
736 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
737 if (auto_input && (*i)->record_enabled ()) {
738 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
739 (*i)->monitor_input (false);
744 if (synced_to_jack()) {
745 _engine.transport_start ();
752 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
756 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
757 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
762 if (actively_recording()) {
766 if (speed > 0.0f && _transport_frame == current_end_frame()) {
770 if (speed < 0.0f && _transport_frame == 0) {
776 /* if we are reversing relative to the current speed, or relative to the speed
777 before the last stop, then we have to do extra work.
780 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
781 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
784 _last_transport_speed = _transport_speed;
785 _transport_speed = speed;
787 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
788 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
789 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
793 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
794 schedule_butler_transport_work ();
800 Session::stop_transport (bool abort)
802 if (_transport_speed == 0.0f) {
806 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
807 _worst_output_latency > current_block_size)
810 /* we need to capture the audio that has still not yet been received by the system
811 at the time the stop is requested, so we have to roll past that time.
813 we want to declick before stopping, so schedule the autostop for one
814 block before the actual end. we'll declick in the subsequent block,
815 and then we'll really be stopped.
818 Event *ev = new Event (Event::StopOnce, Event::Replace,
819 _transport_frame + _worst_output_latency - current_block_size,
823 transport_sub_state |= StopPendingCapture;
824 pending_abort = abort;
828 if ((transport_sub_state & PendingDeclickOut) == 0) {
829 transport_sub_state |= PendingDeclickOut;
830 /* we'll be called again after the declick */
834 realtime_stop (abort);
835 schedule_butler_transport_work ();
839 Session::start_transport ()
841 _last_roll_location = _transport_frame;
843 /* if record status is Enabled, move it to Recording. if its
844 already Recording, move it to Disabled.
847 switch (record_status()) {
855 disable_record (false);
862 if (!synced_to_jack() || _exporting) {
863 actually_start_transport ();
865 waiting_to_start = true;
870 Session::actually_start_transport ()
872 waiting_to_start = false;
874 transport_sub_state |= PendingDeclickIn;
875 _transport_speed = 1.0;
877 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
878 (*i)->realtime_set_speed ((*i)->speed(), true);
881 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
883 TransportStateChange (); /* EMIT SIGNAL */
887 Session::post_transport ()
889 if (post_transport_work & PostTransportAudition) {
890 if (auditioner && auditioner->active()) {
891 process_function = &Session::process_audition;
893 process_function = &Session::process_with_events;
897 if (post_transport_work & PostTransportStop) {
899 transport_sub_state = 0;
902 if (post_transport_work & PostTransportLocate) {
904 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
909 transport_sub_state = 0;
915 post_transport_work = PostTransportWork (0);
919 Session::set_rf_speed (float speed)
922 cumulative_rf_motion = 0;
927 Session::reset_rf_scale (jack_nframes_t motion)
929 cumulative_rf_motion += motion;
931 if (cumulative_rf_motion < 4 * _current_frame_rate) {
933 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
935 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
947 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
949 bool reverse = false;
950 bool non_rt_required = false;
952 if (src == _slave_type) {
956 if (_transport_speed) {
957 error << _("please stop the transport before adjusting slave settings") << endmsg;
958 /* help out non-MVC friendly UI's by telling them the slave type changed */
959 ControlChanged (SlaveType); /* EMIT SIGNAL */
963 // if (src == JACK && Config->get_jack_time_master()) {
973 if (_transport_speed < 0.0) {
985 _slave = new MTC_Slave (*this, *_mtc_port);
988 catch (failed_constructor& err) {
993 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
996 _desired_transport_speed = _transport_speed;
1000 _slave = new JACK_Slave (_engine.jack());
1001 _desired_transport_speed = _transport_speed;
1007 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
1008 if (!(*i)->hidden()) {
1009 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1010 non_rt_required = true;
1012 (*i)->set_slaved (_slave);
1017 reverse_diskstream_buffers ();
1020 if (non_rt_required) {
1021 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1022 schedule_butler_transport_work ();
1026 ControlChanged (SlaveType); /* EMIT SIGNAL */
1032 Session::reverse_diskstream_buffers ()
1034 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1035 schedule_butler_transport_work ();
1039 Session::set_diskstream_speed (AudioDiskstream* stream, float speed)
1041 if (stream->realtime_set_speed (speed, false)) {
1042 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1043 schedule_butler_transport_work ();
1049 Session::set_audio_range (list<AudioRange>& range)
1051 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1052 ev->audio_range = range;
1057 Session::request_play_range (bool yn)
1059 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1064 Session::set_play_range (bool yn)
1066 /* Called from event-processing context */
1068 if (_play_range != yn) {
1073 /* stop transport */
1074 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1078 ControlChanged (PlayRange); /* EMIT SIGNAL */
1083 Session::setup_auto_play ()
1085 /* Called from event-processing context */
1089 _clear_event_type (Event::RangeStop);
1090 _clear_event_type (Event::RangeLocate);
1096 list<AudioRange>::size_type sz = current_audio_range.size();
1100 list<AudioRange>::iterator i = current_audio_range.begin();
1101 list<AudioRange>::iterator next;
1103 while (i != current_audio_range.end()) {
1108 /* locating/stopping is subject to delays for declicking.
1111 jack_nframes_t requested_frame = (*i).end;
1113 if (requested_frame > current_block_size) {
1114 requested_frame -= current_block_size;
1116 requested_frame = 0;
1119 if (next == current_audio_range.end()) {
1120 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1122 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1130 } else if (sz == 1) {
1132 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1137 /* now start rolling at the right place */
1139 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1144 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1147 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1149 request_locate (start, true);
1153 Session::engine_halted ()
1155 /* there will be no more calls to process(), so
1156 we'd better clean up for ourselves, right now.
1158 but first, make sure the butler is out of
1162 g_atomic_int_set (&butler_should_do_transport_work, 0);
1163 post_transport_work = PostTransportWork (0);
1166 realtime_stop (false);
1167 non_realtime_stop (false);
1168 transport_sub_state = 0;
1170 TransportStateChange (); /* EMIT SIGNAL */
1175 Session::xrun_recovery ()
1177 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1179 HaltOnXrun (); /* EMIT SIGNAL */
1181 /* it didn't actually halt, but we need
1182 to handle things in the same way.
1190 Session::update_latency_compensation (bool with_stop, bool abort)
1192 bool update_jack = false;
1194 if (_state_of_the_state & Deletion) {
1198 Glib::RWLock::ReaderLock lm (route_lock);
1199 Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1200 _worst_track_latency = 0;
1202 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1204 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1205 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1208 jack_nframes_t old_latency = (*i)->signal_latency ();
1209 jack_nframes_t track_latency = (*i)->update_total_latency ();
1211 if (old_latency != track_latency) {
1215 if (!(*i)->hidden() && ((*i)->active())) {
1216 _worst_track_latency = max (_worst_track_latency, track_latency);
1220 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1221 (*i)->set_latency_delay (_worst_track_latency);
1224 /* tell JACK to play catch up */
1227 _engine.update_total_latencies ();
1230 set_worst_io_latencies (false);
1232 /* reflect any changes in latencies into capture offsets
1235 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
1236 (*i)->set_capture_offset ();
1241 Session::update_latency_compensation_proxy (void* ignored)
1243 update_latency_compensation (false, false);