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 add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
324 add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
327 _end_location_is_free = false;
328 _have_captured = true;
331 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
332 (*i)->transport_stopped (*now, xnow, abort);
335 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
336 if (!(*i)->hidden()) {
337 (*i)->set_pending_declick (0);
342 commit_reversible_command ();
345 if (_engine.running()) {
346 update_latency_compensation (true, abort);
349 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
351 if (pending_locate_flush) {
352 flush_all_redirects ();
355 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
357 _transport_frame = last_stop_frame;
359 if (synced_to_jack()) {
360 _engine.transport_locate (_transport_frame);
364 #ifndef LEAVE_TRANSPORT_UNADJUSTED
368 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
369 if (!(*i)->hidden()) {
370 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
371 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
374 (*i)->seek (_transport_frame);
379 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
381 #ifdef LEAVE_TRANSPORT_UNADJUSTED
385 last_stop_frame = _transport_frame;
387 send_full_time_code ();
388 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
389 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
393 /* XXX its a little odd that we're doing this here
394 when realtime_stop(), which has already executed,
398 if (!Config->get_latched_record_enable()) {
399 g_atomic_int_set (&_record_status, Disabled);
401 g_atomic_int_set (&_record_status, Enabled);
403 RecordStateChanged (); /* emit signal */
406 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
407 /* capture start has been changed, so save pending state */
408 save_state ("", true);
411 /* always try to get rid of this */
413 remove_pending_capture_state ();
415 /* save the current state of things if appropriate */
418 save_state (_current_snapshot_name);
421 if (post_transport_work & PostTransportDuration) {
422 DurationChanged (); /* EMIT SIGNAL */
425 if (post_transport_work & PostTransportStop) {
428 /* do not turn off autoloop on stop */
432 PositionChanged (_transport_frame); /* EMIT SIGNAL */
433 TransportStateChange (); /* EMIT SIGNAL */
435 /* and start it up again if relevant */
437 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
438 request_transport_speed (1.0);
439 pending_locate_roll = false;
444 Session::check_declick_out ()
446 bool locate_required = transport_sub_state & PendingLocate;
448 /* this is called after a process() iteration. if PendingDeclickOut was set,
449 it means that we were waiting to declick the output (which has just been
450 done) before doing something else. this is where we do that "something else".
452 note: called from the audio thread.
455 if (transport_sub_state & PendingDeclickOut) {
457 if (locate_required) {
458 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
459 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
461 stop_transport (pending_abort);
462 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
468 Session::set_auto_loop (bool yn)
470 /* Called from event-handling context */
472 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
478 if (yn && seamless_loop && synced_to_jack()) {
479 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
480 "Recommend changing the configured options")
486 if ((auto_loop = yn)) {
491 if ((loc = _locations.auto_loop_location()) != 0) {
494 // set all diskstreams to use internal looping
495 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
496 if (!(*i)->hidden()) {
497 (*i)->set_loop (loc);
502 // set all diskstreams to NOT use internal looping
503 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
504 if (!(*i)->hidden()) {
510 /* stick in the loop event */
512 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
515 /* locate to start of loop and roll if current pos is outside of the loop range */
516 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
517 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
521 // locate to current position (+ 1 to force reload)
522 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
530 clear_events (Event::AutoLoop);
532 // set all diskstreams to NOT use internal looping
533 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
534 if (!(*i)->hidden()) {
541 ControlChanged (AutoLoop); /* EMIT SIGNAL */
545 Session::flush_all_redirects ()
547 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
548 (*i)->flush_redirects ();
553 Session::start_locate (jack_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 (jack_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;
597 _transport_frame = target_frame;
599 if (_transport_speed && (!with_loop || loop_changing)) {
600 /* schedule a declick. we'll be called again when its done */
602 if (!(transport_sub_state & PendingDeclickOut)) {
603 transport_sub_state |= (PendingDeclickOut|PendingLocate);
604 pending_locate_frame = target_frame;
605 pending_locate_roll = with_roll;
606 pending_locate_flush = with_flush;
611 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
612 realtime_stop (false);
615 if ( !with_loop || loop_changing) {
617 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
620 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
623 schedule_butler_transport_work ();
627 /* this is functionally what clear_clicks() does but with a tentative lock */
629 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
631 if (clickm.locked()) {
633 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
642 /* switch from input if we're going to roll */
643 if (Config->get_use_hardware_monitoring()) {
644 /* Even though this is called from RT context we are using
645 a non-tentative rwlock here, because the action must occur.
646 The rarity and short potential lock duration makes this "OK"
648 Glib::RWLock::ReaderLock dsm (diskstream_lock);
649 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
650 if ((*i)->record_enabled ()) {
651 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
652 (*i)->monitor_input (!auto_input);
657 /* otherwise we're going to stop, so do the opposite */
658 if (Config->get_use_hardware_monitoring()) {
659 /* Even though this is called from RT context we are using
660 a non-tentative rwlock here, because the action must occur.
661 The rarity and short potential lock duration makes this "OK"
663 Glib::RWLock::ReaderLock dsm (diskstream_lock);
664 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
665 if ((*i)->record_enabled ()) {
666 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
667 (*i)->monitor_input (true);
673 /* cancel autoloop 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_auto_loop(false);
683 loop_changing = false;
687 Session::set_transport_speed (float speed, bool abort)
689 if (_transport_speed == speed) {
694 speed = min (8.0f, speed);
695 } else if (speed < 0) {
696 speed = max (-8.0f, speed);
699 if (transport_rolling() && speed == 0.0) {
701 if (Config->get_use_hardware_monitoring())
703 /* Even though this is called from RT context we are using
704 a non-tentative rwlock here, because the action must occur.
705 The rarity and short potential lock duration makes this "OK"
707 Glib::RWLock::ReaderLock dsm (diskstream_lock);
708 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
709 if ((*i)->record_enabled ()) {
710 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
711 (*i)->monitor_input (true);
716 if (synced_to_jack ()) {
717 _engine.transport_stop ();
719 stop_transport (abort);
722 } else if (transport_stopped() && speed == 1.0) {
724 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
728 if (Config->get_use_hardware_monitoring()) {
729 /* Even though this is called from RT context we are using
730 a non-tentative rwlock here, because the action must occur.
731 The rarity and short potential lock duration makes this "OK"
733 Glib::RWLock::ReaderLock dsm (diskstream_lock);
734 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
735 if (auto_input && (*i)->record_enabled ()) {
736 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
737 (*i)->monitor_input (false);
742 if (synced_to_jack()) {
743 _engine.transport_start ();
750 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
754 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
755 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
760 if (actively_recording()) {
764 if (speed > 0.0f && _transport_frame == current_end_frame()) {
768 if (speed < 0.0f && _transport_frame == 0) {
774 /* if we are reversing relative to the current speed, or relative to the speed
775 before the last stop, then we have to do extra work.
778 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
779 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
782 _last_transport_speed = _transport_speed;
783 _transport_speed = speed;
785 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
786 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
787 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
791 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
792 schedule_butler_transport_work ();
798 Session::stop_transport (bool abort)
800 if (_transport_speed == 0.0f) {
804 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
805 _worst_output_latency > current_block_size)
808 /* we need to capture the audio that has still not yet been received by the system
809 at the time the stop is requested, so we have to roll past that time.
811 we want to declick before stopping, so schedule the autostop for one
812 block before the actual end. we'll declick in the subsequent block,
813 and then we'll really be stopped.
816 Event *ev = new Event (Event::StopOnce, Event::Replace,
817 _transport_frame + _worst_output_latency - current_block_size,
821 transport_sub_state |= StopPendingCapture;
822 pending_abort = abort;
826 if ((transport_sub_state & PendingDeclickOut) == 0) {
827 transport_sub_state |= PendingDeclickOut;
828 /* we'll be called again after the declick */
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()) {
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 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
876 (*i)->realtime_set_speed ((*i)->speed(), true);
879 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
881 TransportStateChange (); /* EMIT SIGNAL */
885 Session::post_transport ()
887 if (post_transport_work & PostTransportAudition) {
888 if (auditioner && auditioner->active()) {
889 process_function = &Session::process_audition;
891 process_function = &Session::process_with_events;
895 if (post_transport_work & PostTransportStop) {
897 transport_sub_state = 0;
900 if (post_transport_work & PostTransportLocate) {
902 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
907 transport_sub_state = 0;
913 post_transport_work = PostTransportWork (0);
917 Session::set_rf_speed (float speed)
920 cumulative_rf_motion = 0;
925 Session::reset_rf_scale (jack_nframes_t motion)
927 cumulative_rf_motion += motion;
929 if (cumulative_rf_motion < 4 * _current_frame_rate) {
931 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
933 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
945 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
947 bool reverse = false;
948 bool non_rt_required = false;
950 if (src == _slave_type) {
954 if (_transport_speed) {
955 error << _("please stop the transport before adjusting slave settings") << endmsg;
956 /* help out non-MVC friendly UI's by telling them the slave type changed */
957 ControlChanged (SlaveType); /* EMIT SIGNAL */
961 // if (src == JACK && Config->get_jack_time_master()) {
971 if (_transport_speed < 0.0) {
983 _slave = new MTC_Slave (*this, *_mtc_port);
986 catch (failed_constructor& err) {
991 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
994 _desired_transport_speed = _transport_speed;
998 _slave = new JACK_Slave (_engine.jack());
999 _desired_transport_speed = _transport_speed;
1005 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
1006 if (!(*i)->hidden()) {
1007 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1008 non_rt_required = true;
1010 (*i)->set_slaved (_slave);
1015 reverse_diskstream_buffers ();
1018 if (non_rt_required) {
1019 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1020 schedule_butler_transport_work ();
1024 ControlChanged (SlaveType); /* EMIT SIGNAL */
1030 Session::reverse_diskstream_buffers ()
1032 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1033 schedule_butler_transport_work ();
1037 Session::set_diskstream_speed (AudioDiskstream* stream, float speed)
1039 if (stream->realtime_set_speed (speed, false)) {
1040 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1041 schedule_butler_transport_work ();
1047 Session::set_audio_range (list<AudioRange>& range)
1049 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1050 ev->audio_range = range;
1055 Session::request_play_range (bool yn)
1057 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1062 Session::set_play_range (bool yn)
1064 /* Called from event-processing context */
1066 if (_play_range != yn) {
1071 /* stop transport */
1072 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1076 ControlChanged (PlayRange); /* EMIT SIGNAL */
1081 Session::setup_auto_play ()
1083 /* Called from event-processing context */
1087 _clear_event_type (Event::RangeStop);
1088 _clear_event_type (Event::RangeLocate);
1094 list<AudioRange>::size_type sz = current_audio_range.size();
1098 list<AudioRange>::iterator i = current_audio_range.begin();
1099 list<AudioRange>::iterator next;
1101 while (i != current_audio_range.end()) {
1106 /* locating/stopping is subject to delays for declicking.
1109 jack_nframes_t requested_frame = (*i).end;
1111 if (requested_frame > current_block_size) {
1112 requested_frame -= current_block_size;
1114 requested_frame = 0;
1117 if (next == current_audio_range.end()) {
1118 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1120 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1128 } else if (sz == 1) {
1130 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1135 /* now start rolling at the right place */
1137 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1142 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1145 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1147 request_locate (start, true);
1151 Session::engine_halted ()
1153 /* there will be no more calls to process(), so
1154 we'd better clean up for ourselves, right now.
1156 but first, make sure the butler is out of
1160 g_atomic_int_set (&butler_should_do_transport_work, 0);
1161 post_transport_work = PostTransportWork (0);
1164 realtime_stop (false);
1165 non_realtime_stop (false);
1166 transport_sub_state = 0;
1168 TransportStateChange (); /* EMIT SIGNAL */
1173 Session::xrun_recovery ()
1175 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1177 HaltOnXrun (); /* EMIT SIGNAL */
1179 /* it didn't actually halt, but we need
1180 to handle things in the same way.
1188 Session::update_latency_compensation (bool with_stop, bool abort)
1190 bool update_jack = false;
1192 if (_state_of_the_state & Deletion) {
1196 Glib::RWLock::ReaderLock lm (route_lock);
1197 Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1198 _worst_track_latency = 0;
1200 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1202 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1203 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1206 jack_nframes_t old_latency = (*i)->signal_latency ();
1207 jack_nframes_t track_latency = (*i)->update_total_latency ();
1209 if (old_latency != track_latency) {
1213 if (!(*i)->hidden() && ((*i)->active())) {
1214 _worst_track_latency = max (_worst_track_latency, track_latency);
1218 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1219 (*i)->set_latency_delay (_worst_track_latency);
1222 /* tell JACK to play catch up */
1225 _engine.update_total_latencies ();
1228 set_worst_io_latencies (false);
1230 /* reflect any changes in latencies into capture offsets
1233 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
1234 (*i)->set_capture_offset ();
1239 Session::update_latency_compensation_proxy (void* ignored)
1241 update_latency_compensation (false, false);