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;
51 Session::request_input_change_handling ()
53 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
58 Session::request_slave_source (SlaveSource src, jack_nframes_t pos)
60 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, pos, 0.0);
62 if (src == Session::JACK) {
63 /* could set_seamless_loop() be disposed of entirely?*/
64 set_seamless_loop (false);
67 set_seamless_loop (true);
74 Session::request_transport_speed (float speed)
76 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
81 Session::request_diskstream_speed (AudioDiskstream& ds, float speed)
83 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
89 Session::request_stop (bool abort)
91 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
96 Session::request_locate (jack_nframes_t target_frame, bool with_roll)
98 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
103 Session::force_locate (jack_nframes_t target_frame, bool with_roll)
105 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
110 Session::request_auto_loop (bool yn)
113 Location *location = _locations.auto_loop_location();
115 if (location == 0 && yn) {
116 error << _("Cannot loop - no loop range defined")
121 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
124 if (!yn && seamless_loop && transport_rolling()) {
125 // request an immediate locate to refresh the diskstreams
126 // after disabling looping
127 request_locate (_transport_frame-1, true);
132 Session::set_seamless_loop (bool yn)
134 if (seamless_loop != yn) {
137 if (auto_loop && transport_rolling()) {
138 // to reset diskstreams etc
139 request_auto_loop (true);
142 ControlChanged (SeamlessLoop); /* EMIT */
147 Session::realtime_stop (bool abort)
149 /* assume that when we start, we'll be moving forwards */
151 // FIXME: where should this really be? [DR]
152 //send_full_time_code();
153 deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
154 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
156 if (_transport_speed < 0.0f) {
157 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
159 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
162 if (actively_recording()) {
164 /* move the transport position back to where the
165 request for a stop was noticed. we rolled
166 past that point to pick up delayed input.
169 #ifndef LEAVE_TRANSPORT_UNADJUSTED
170 decrement_transport_position (_worst_output_latency);
173 /* the duration change is not guaranteed to have happened, but is likely */
175 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
179 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
182 _clear_event_type (Event::StopOnce);
183 _clear_event_type (Event::RangeStop);
184 _clear_event_type (Event::RangeLocate);
186 disable_record (true);
188 reset_slave_state ();
190 _transport_speed = 0;
192 transport_sub_state = (auto_return ? AutoReturning : 0);
196 Session::butler_transport_work ()
198 Glib::RWLock::ReaderLock rm (route_lock);
199 Glib::RWLock::ReaderLock dsm (diskstream_lock);
201 if (post_transport_work & PostTransportCurveRealloc) {
202 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
203 (*i)->curve_reallocate();
207 if (post_transport_work & PostTransportInputChange) {
208 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
209 (*i)->non_realtime_input_change ();
213 if (post_transport_work & PostTransportSpeed) {
214 non_realtime_set_speed ();
217 if (post_transport_work & PostTransportReverse) {
221 cumulative_rf_motion = 0;
224 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
225 if (!(*i)->hidden()) {
226 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
227 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
230 (*i)->seek (_transport_frame);
236 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
237 non_realtime_stop (post_transport_work & PostTransportAbort);
240 if (post_transport_work & PostTransportOverWrite) {
241 non_realtime_overwrite ();
244 if (post_transport_work & PostTransportAudition) {
245 non_realtime_set_audition ();
248 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
252 Session::non_realtime_set_speed ()
254 Glib::RWLock::ReaderLock lm (diskstream_lock);
256 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
257 (*i)->non_realtime_set_speed ();
262 Session::non_realtime_overwrite ()
264 Glib::RWLock::ReaderLock lm (diskstream_lock);
266 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
267 if ((*i)->pending_overwrite) {
268 (*i)->overwrite_existing_buffers ();
274 Session::non_realtime_stop (bool abort)
282 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
283 if ((*i)->get_captured_frames () != 0) {
289 /* stop and locate are merged here because they share a lot of common stuff */
292 now = localtime (&xnow);
295 auditioner->cancel_audition ();
299 cumulative_rf_motion = 0;
303 begin_reversible_command ("capture");
305 Location* loc = _locations.end_location();
306 bool change_end = false;
308 if (_transport_frame < loc->end()) {
310 /* stopped recording before current end */
312 if (_end_location_is_free) {
314 /* first capture for this session, move end back to where we are */
319 } else if (_transport_frame > loc->end()) {
321 /* stopped recording after the current end, extend it */
327 add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
328 add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
331 _end_location_is_free = false;
332 _have_captured = true;
335 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
336 (*i)->transport_stopped (*now, xnow, abort);
339 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
340 if (!(*i)->hidden()) {
341 (*i)->set_pending_declick (0);
346 commit_reversible_command ();
349 if (_engine.running()) {
350 update_latency_compensation (true, abort);
353 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
355 if (pending_locate_flush) {
356 flush_all_redirects ();
359 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
361 _transport_frame = last_stop_frame;
363 if (synced_to_jack()) {
364 _engine.transport_locate (_transport_frame);
368 #ifndef LEAVE_TRANSPORT_UNADJUSTED
372 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
373 if (!(*i)->hidden()) {
374 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
375 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
378 (*i)->seek (_transport_frame);
384 //deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
386 #ifdef LEAVE_TRANSPORT_UNADJUSTED
390 last_stop_frame = _transport_frame;
394 /* XXX its a little odd that we're doing this here
395 when realtime_stop(), which has already executed,
399 if (!Config->get_latched_record_enable()) {
400 g_atomic_int_set (&_record_status, Disabled);
402 g_atomic_int_set (&_record_status, Enabled);
404 RecordStateChanged (); /* emit signal */
407 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
408 /* capture start has been changed, so save pending state */
409 save_state ("", true);
412 /* always try to get rid of this */
414 remove_pending_capture_state ();
416 /* save the current state of things if appropriate */
419 save_state (_current_snapshot_name);
422 if (post_transport_work & PostTransportDuration) {
423 DurationChanged (); /* EMIT SIGNAL */
426 if (post_transport_work & PostTransportStop) {
429 /* do not turn off autoloop on stop */
433 PositionChanged (_transport_frame); /* EMIT SIGNAL */
434 TransportStateChange (); /* EMIT SIGNAL */
436 /* and start it up again if relevant */
438 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
439 request_transport_speed (1.0);
440 pending_locate_roll = false;
445 Session::check_declick_out ()
447 bool locate_required = transport_sub_state & PendingLocate;
449 /* this is called after a process() iteration. if PendingDeclickOut was set,
450 it means that we were waiting to declick the output (which has just been
451 done) before doing something else. this is where we do that "something else".
453 note: called from the audio thread.
456 if (transport_sub_state & PendingDeclickOut) {
458 if (locate_required) {
459 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
460 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
462 stop_transport (pending_abort);
463 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
469 Session::set_auto_loop (bool yn)
471 /* Called from event-handling context */
473 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
479 if (yn && seamless_loop && synced_to_jack()) {
480 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
481 "Recommend changing the configured options")
487 if ((auto_loop = yn)) {
492 if ((loc = _locations.auto_loop_location()) != 0) {
495 // set all diskstreams to use internal looping
496 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
497 if (!(*i)->hidden()) {
498 (*i)->set_loop (loc);
503 // set all diskstreams to NOT use internal looping
504 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
505 if (!(*i)->hidden()) {
511 /* stick in the loop event */
513 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
516 /* locate to start of loop and roll if current pos is outside of the loop range */
517 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
518 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
522 // locate to current position (+ 1 to force reload)
523 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
531 clear_events (Event::AutoLoop);
533 // set all diskstreams to NOT use internal looping
534 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
535 if (!(*i)->hidden()) {
542 ControlChanged (AutoLoop); /* EMIT SIGNAL */
546 Session::flush_all_redirects ()
548 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
549 (*i)->flush_redirects ();
554 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
556 if (synced_to_jack()) {
561 _slave->speed_and_position (sp, pos);
563 if (target_frame != pos) {
565 /* tell JACK to change transport position, and we will
566 follow along later in ::follow_slave()
569 _engine.transport_locate (target_frame);
571 if (sp != 1.0f && with_roll) {
572 _engine.transport_start ();
579 locate (target_frame, with_roll, with_flush, with_loop);
584 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
586 if (actively_recording()) {
590 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
592 set_transport_speed (1.0, false);
594 loop_changing = false;
599 // [DR] FIXME: find out exactly where this should go below
600 _transport_frame = target_frame;
601 smpte_time(_transport_frame, transmitting_smpte_time);
602 outbound_mtc_smpte_frame = _transport_frame;
603 next_quarter_frame_to_send = 0;
605 if (_transport_speed && (!with_loop || loop_changing)) {
606 /* schedule a declick. we'll be called again when its done */
608 if (!(transport_sub_state & PendingDeclickOut)) {
609 transport_sub_state |= (PendingDeclickOut|PendingLocate);
610 pending_locate_frame = target_frame;
611 pending_locate_roll = with_roll;
612 pending_locate_flush = with_flush;
617 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
618 realtime_stop (false);
621 if ( !with_loop || loop_changing) {
623 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
626 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
629 schedule_butler_transport_work ();
633 /* this is functionally what clear_clicks() does but with a tentative lock */
635 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
637 if (clickm.locked()) {
639 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
648 /* switch from input if we're going to roll */
649 if (Config->get_use_hardware_monitoring()) {
650 /* Even though this is called from RT context we are using
651 a non-tentative rwlock here, because the action must occur.
652 The rarity and short potential lock duration makes this "OK"
654 Glib::RWLock::ReaderLock dsm (diskstream_lock);
655 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
656 if ((*i)->record_enabled ()) {
657 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
658 (*i)->monitor_input (!auto_input);
663 /* otherwise we're going to stop, so do the opposite */
664 if (Config->get_use_hardware_monitoring()) {
665 /* Even though this is called from RT context we are using
666 a non-tentative rwlock here, because the action must occur.
667 The rarity and short potential lock duration makes this "OK"
669 Glib::RWLock::ReaderLock dsm (diskstream_lock);
670 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
671 if ((*i)->record_enabled ()) {
672 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
673 (*i)->monitor_input (true);
679 /* cancel autoloop if transport pos outside of loop range */
681 Location* al = _locations.auto_loop_location();
683 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
684 // cancel looping directly, this is called from event handling context
685 set_auto_loop(false);
689 loop_changing = false;
691 _send_smpte_update = true;
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 (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_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 (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_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 (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_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 (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
884 (*i)->realtime_set_speed ((*i)->speed(), true);
887 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
889 TransportStateChange (); /* EMIT SIGNAL */
892 /** Do any transport work in the audio thread that needs to be done after the
893 * transport thread is finished. Audio thread, realtime safe.
896 Session::post_transport ()
898 if (post_transport_work & PostTransportAudition) {
899 if (auditioner && auditioner->active()) {
900 process_function = &Session::process_audition;
902 process_function = &Session::process_with_events;
906 if (post_transport_work & PostTransportStop) {
908 transport_sub_state = 0;
911 if (post_transport_work & PostTransportLocate) {
913 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
918 transport_sub_state = 0;
924 post_transport_work = PostTransportWork (0);
928 Session::set_rf_speed (float speed)
931 cumulative_rf_motion = 0;
936 Session::reset_rf_scale (jack_nframes_t motion)
938 cumulative_rf_motion += motion;
940 if (cumulative_rf_motion < 4 * _current_frame_rate) {
942 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
944 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
956 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
958 bool reverse = false;
959 bool non_rt_required = false;
961 if (src == _slave_type) {
965 if (_transport_speed) {
966 error << _("please stop the transport before adjusting slave settings") << endmsg;
967 /* help out non-MVC friendly UI's by telling them the slave type changed */
968 ControlChanged (SlaveType); /* EMIT SIGNAL */
972 // if (src == JACK && Config->get_jack_time_master()) {
982 if (_transport_speed < 0.0) {
994 _slave = new MTC_Slave (*this, *_mtc_port);
997 catch (failed_constructor& err) {
1002 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1005 _desired_transport_speed = _transport_speed;
1009 _slave = new JACK_Slave (_engine.jack());
1010 _desired_transport_speed = _transport_speed;
1016 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
1017 if (!(*i)->hidden()) {
1018 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1019 non_rt_required = true;
1021 (*i)->set_slaved (_slave);
1026 reverse_diskstream_buffers ();
1029 if (non_rt_required) {
1030 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1031 schedule_butler_transport_work ();
1035 ControlChanged (SlaveType); /* EMIT SIGNAL */
1041 Session::reverse_diskstream_buffers ()
1043 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1044 schedule_butler_transport_work ();
1048 Session::set_diskstream_speed (AudioDiskstream* stream, float speed)
1050 if (stream->realtime_set_speed (speed, false)) {
1051 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1052 schedule_butler_transport_work ();
1058 Session::set_audio_range (list<AudioRange>& range)
1060 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1061 ev->audio_range = range;
1066 Session::request_play_range (bool yn)
1068 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1073 Session::set_play_range (bool yn)
1075 /* Called from event-processing context */
1077 if (_play_range != yn) {
1082 /* stop transport */
1083 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1087 ControlChanged (PlayRange); /* EMIT SIGNAL */
1092 Session::setup_auto_play ()
1094 /* Called from event-processing context */
1098 _clear_event_type (Event::RangeStop);
1099 _clear_event_type (Event::RangeLocate);
1105 list<AudioRange>::size_type sz = current_audio_range.size();
1109 list<AudioRange>::iterator i = current_audio_range.begin();
1110 list<AudioRange>::iterator next;
1112 while (i != current_audio_range.end()) {
1117 /* locating/stopping is subject to delays for declicking.
1120 jack_nframes_t requested_frame = (*i).end;
1122 if (requested_frame > current_block_size) {
1123 requested_frame -= current_block_size;
1125 requested_frame = 0;
1128 if (next == current_audio_range.end()) {
1129 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1131 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1139 } else if (sz == 1) {
1141 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1146 /* now start rolling at the right place */
1148 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1153 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1156 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1158 request_locate (start, true);
1162 Session::engine_halted ()
1164 /* there will be no more calls to process(), so
1165 we'd better clean up for ourselves, right now.
1167 but first, make sure the butler is out of
1171 g_atomic_int_set (&butler_should_do_transport_work, 0);
1172 post_transport_work = PostTransportWork (0);
1175 realtime_stop (false);
1176 non_realtime_stop (false);
1177 transport_sub_state = 0;
1179 TransportStateChange (); /* EMIT SIGNAL */
1184 Session::xrun_recovery ()
1186 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1188 HaltOnXrun (); /* EMIT SIGNAL */
1190 /* it didn't actually halt, but we need
1191 to handle things in the same way.
1199 Session::update_latency_compensation (bool with_stop, bool abort)
1201 bool update_jack = false;
1203 if (_state_of_the_state & Deletion) {
1207 Glib::RWLock::ReaderLock lm (route_lock);
1208 Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1209 _worst_track_latency = 0;
1211 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1213 (*i)->transport_stopped (abort, (post_transport_work & PostTransportLocate),
1214 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1217 jack_nframes_t old_latency = (*i)->signal_latency ();
1218 jack_nframes_t track_latency = (*i)->update_total_latency ();
1220 if (old_latency != track_latency) {
1224 if (!(*i)->hidden() && ((*i)->active())) {
1225 _worst_track_latency = max (_worst_track_latency, track_latency);
1229 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1230 (*i)->set_latency_delay (_worst_track_latency);
1233 /* tell JACK to play catch up */
1236 _engine.update_total_latencies ();
1239 set_worst_io_latencies (false);
1241 /* reflect any changes in latencies into capture offsets
1244 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
1245 (*i)->set_capture_offset ();
1250 Session::update_latency_compensation_proxy (void* ignored)
1252 update_latency_compensation (false, false);