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 (Diskstream& ds, float speed)
84 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
90 Session::request_stop (bool abort)
92 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
97 Session::request_locate (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 // FIXME: where should this really be? [DR]
153 //send_full_time_code();
154 deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
155 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
157 if (_transport_speed < 0.0f) {
158 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
160 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
163 if (actively_recording()) {
165 /* move the transport position back to where the
166 request for a stop was noticed. we rolled
167 past that point to pick up delayed input.
170 #ifndef LEAVE_TRANSPORT_UNADJUSTED
171 decrement_transport_position (_worst_output_latency);
174 /* the duration change is not guaranteed to have happened, but is likely */
176 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
180 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
183 _clear_event_type (Event::StopOnce);
184 _clear_event_type (Event::RangeStop);
185 _clear_event_type (Event::RangeLocate);
187 disable_record (true);
189 reset_slave_state ();
191 _transport_speed = 0;
193 transport_sub_state = (auto_return ? AutoReturning : 0);
197 Session::butler_transport_work ()
199 Glib::RWLock::ReaderLock rm (route_lock);
200 Glib::RWLock::ReaderLock dsm (diskstream_lock);
202 if (post_transport_work & PostTransportCurveRealloc) {
203 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
204 (*i)->curve_reallocate();
208 if (post_transport_work & PostTransportInputChange) {
209 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
210 (*i)->non_realtime_input_change ();
214 if (post_transport_work & PostTransportSpeed) {
215 non_realtime_set_speed ();
218 if (post_transport_work & PostTransportReverse) {
222 cumulative_rf_motion = 0;
225 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
226 if (!(*i)->hidden()) {
227 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
228 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
231 (*i)->seek (_transport_frame);
237 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
238 non_realtime_stop (post_transport_work & PostTransportAbort);
241 if (post_transport_work & PostTransportOverWrite) {
242 non_realtime_overwrite ();
245 if (post_transport_work & PostTransportAudition) {
246 non_realtime_set_audition ();
249 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
253 Session::non_realtime_set_speed ()
255 Glib::RWLock::ReaderLock lm (diskstream_lock);
257 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
258 (*i)->non_realtime_set_speed ();
263 Session::non_realtime_overwrite ()
265 Glib::RWLock::ReaderLock lm (diskstream_lock);
267 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
268 if ((*i)->pending_overwrite) {
269 (*i)->overwrite_existing_buffers ();
275 Session::non_realtime_stop (bool abort)
283 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
284 if ((*i)->get_captured_frames () != 0) {
290 /* stop and locate are merged here because they share a lot of common stuff */
293 now = localtime (&xnow);
296 auditioner->cancel_audition ();
300 cumulative_rf_motion = 0;
304 begin_reversible_command ("capture");
306 Location* loc = _locations.end_location();
307 bool change_end = false;
309 if (_transport_frame < loc->end()) {
311 /* stopped recording before current end */
313 if (_end_location_is_free) {
315 /* first capture for this session, move end back to where we are */
320 } else if (_transport_frame > loc->end()) {
322 /* stopped recording after the current end, extend it */
328 add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
329 add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
332 _end_location_is_free = false;
333 _have_captured = true;
336 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
337 (*i)->transport_stopped (*now, xnow, abort);
340 for (RouteList::iterator i = routes.begin(); i != routes.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 (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_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);
385 //deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
387 #ifdef LEAVE_TRANSPORT_UNADJUSTED
391 last_stop_frame = _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;
600 // [DR] FIXME: find out exactly where this should go below
601 _transport_frame = target_frame;
602 smpte_time(_transport_frame, transmitting_smpte_time);
603 outbound_mtc_smpte_frame = _transport_frame;
604 next_quarter_frame_to_send = 0;
606 if (_transport_speed && (!with_loop || loop_changing)) {
607 /* schedule a declick. we'll be called again when its done */
609 if (!(transport_sub_state & PendingDeclickOut)) {
610 transport_sub_state |= (PendingDeclickOut|PendingLocate);
611 pending_locate_frame = target_frame;
612 pending_locate_roll = with_roll;
613 pending_locate_flush = with_flush;
618 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
619 realtime_stop (false);
622 if ( !with_loop || loop_changing) {
624 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
627 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
630 schedule_butler_transport_work ();
634 /* this is functionally what clear_clicks() does but with a tentative lock */
636 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
638 if (clickm.locked()) {
640 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
649 /* switch from input if we're going to roll */
650 if (Config->get_use_hardware_monitoring()) {
651 /* Even though this is called from RT context we are using
652 a non-tentative rwlock here, because the action must occur.
653 The rarity and short potential lock duration makes this "OK"
655 Glib::RWLock::ReaderLock dsm (diskstream_lock);
656 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
657 if ((*i)->record_enabled ()) {
658 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
659 (*i)->monitor_input (!auto_input);
664 /* otherwise we're going to stop, so do the opposite */
665 if (Config->get_use_hardware_monitoring()) {
666 /* Even though this is called from RT context we are using
667 a non-tentative rwlock here, because the action must occur.
668 The rarity and short potential lock duration makes this "OK"
670 Glib::RWLock::ReaderLock dsm (diskstream_lock);
671 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
672 if ((*i)->record_enabled ()) {
673 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
674 (*i)->monitor_input (true);
680 /* cancel autoloop if transport pos outside of loop range */
682 Location* al = _locations.auto_loop_location();
684 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
685 // cancel looping directly, this is called from event handling context
686 set_auto_loop(false);
690 loop_changing = false;
692 _send_smpte_update = true;
696 Session::set_transport_speed (float speed, bool abort)
698 if (_transport_speed == speed) {
703 speed = min (8.0f, speed);
704 } else if (speed < 0) {
705 speed = max (-8.0f, speed);
708 if (transport_rolling() && speed == 0.0) {
710 if (Config->get_use_hardware_monitoring())
712 /* Even though this is called from RT context we are using
713 a non-tentative rwlock here, because the action must occur.
714 The rarity and short potential lock duration makes this "OK"
716 Glib::RWLock::ReaderLock dsm (diskstream_lock);
717 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
718 if ((*i)->record_enabled ()) {
719 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
720 (*i)->monitor_input (true);
725 if (synced_to_jack ()) {
726 _engine.transport_stop ();
728 stop_transport (abort);
731 } else if (transport_stopped() && speed == 1.0) {
733 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
737 if (Config->get_use_hardware_monitoring()) {
738 /* Even though this is called from RT context we are using
739 a non-tentative rwlock here, because the action must occur.
740 The rarity and short potential lock duration makes this "OK"
742 Glib::RWLock::ReaderLock dsm (diskstream_lock);
743 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
744 if (auto_input && (*i)->record_enabled ()) {
745 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
746 (*i)->monitor_input (false);
751 if (synced_to_jack()) {
752 _engine.transport_start ();
759 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
763 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
764 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
769 if (actively_recording()) {
773 if (speed > 0.0f && _transport_frame == current_end_frame()) {
777 if (speed < 0.0f && _transport_frame == 0) {
783 /* if we are reversing relative to the current speed, or relative to the speed
784 before the last stop, then we have to do extra work.
787 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
788 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
791 _last_transport_speed = _transport_speed;
792 _transport_speed = speed;
794 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
795 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
796 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
800 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
801 schedule_butler_transport_work ();
807 Session::stop_transport (bool abort)
809 if (_transport_speed == 0.0f) {
813 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
814 _worst_output_latency > current_block_size)
817 /* we need to capture the audio that has still not yet been received by the system
818 at the time the stop is requested, so we have to roll past that time.
820 we want to declick before stopping, so schedule the autostop for one
821 block before the actual end. we'll declick in the subsequent block,
822 and then we'll really be stopped.
825 Event *ev = new Event (Event::StopOnce, Event::Replace,
826 _transport_frame + _worst_output_latency - current_block_size,
830 transport_sub_state |= StopPendingCapture;
831 pending_abort = abort;
835 if ((transport_sub_state & PendingDeclickOut) == 0) {
836 transport_sub_state |= PendingDeclickOut;
837 /* we'll be called again after the declick */
841 realtime_stop (abort);
842 schedule_butler_transport_work ();
846 Session::start_transport ()
848 _last_roll_location = _transport_frame;
850 /* if record status is Enabled, move it to Recording. if its
851 already Recording, move it to Disabled.
854 switch (record_status()) {
862 disable_record (false);
869 if (!synced_to_jack() || _exporting) {
870 actually_start_transport ();
872 waiting_to_start = true;
877 Session::actually_start_transport ()
879 waiting_to_start = false;
881 transport_sub_state |= PendingDeclickIn;
882 _transport_speed = 1.0;
884 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
885 (*i)->realtime_set_speed ((*i)->speed(), true);
888 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
890 TransportStateChange (); /* EMIT SIGNAL */
893 /** Do any transport work in the audio thread that needs to be done after the
894 * transport thread is finished. Audio thread, realtime safe.
897 Session::post_transport ()
899 if (post_transport_work & PostTransportAudition) {
900 if (auditioner && auditioner->active()) {
901 process_function = &Session::process_audition;
903 process_function = &Session::process_with_events;
907 if (post_transport_work & PostTransportStop) {
909 transport_sub_state = 0;
912 if (post_transport_work & PostTransportLocate) {
914 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
919 transport_sub_state = 0;
925 post_transport_work = PostTransportWork (0);
929 Session::set_rf_speed (float speed)
932 cumulative_rf_motion = 0;
937 Session::reset_rf_scale (jack_nframes_t motion)
939 cumulative_rf_motion += motion;
941 if (cumulative_rf_motion < 4 * _current_frame_rate) {
943 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
945 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
957 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
959 bool reverse = false;
960 bool non_rt_required = false;
962 if (src == _slave_type) {
966 if (_transport_speed) {
967 error << _("please stop the transport before adjusting slave settings") << endmsg;
968 /* help out non-MVC friendly UI's by telling them the slave type changed */
969 ControlChanged (SlaveType); /* EMIT SIGNAL */
973 // if (src == JACK && Config->get_jack_time_master()) {
983 if (_transport_speed < 0.0) {
995 _slave = new MTC_Slave (*this, *_mtc_port);
998 catch (failed_constructor& err) {
1003 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1006 _desired_transport_speed = _transport_speed;
1010 _slave = new JACK_Slave (_engine.jack());
1011 _desired_transport_speed = _transport_speed;
1017 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
1018 if (!(*i)->hidden()) {
1019 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1020 non_rt_required = true;
1022 (*i)->set_slaved (_slave);
1027 reverse_diskstream_buffers ();
1030 if (non_rt_required) {
1031 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1032 schedule_butler_transport_work ();
1036 ControlChanged (SlaveType); /* EMIT SIGNAL */
1042 Session::reverse_diskstream_buffers ()
1044 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1045 schedule_butler_transport_work ();
1049 Session::set_diskstream_speed (Diskstream* stream, float speed)
1051 if (stream->realtime_set_speed (speed, false)) {
1052 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1053 schedule_butler_transport_work ();
1059 Session::set_audio_range (list<AudioRange>& range)
1061 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1062 ev->audio_range = range;
1067 Session::request_play_range (bool yn)
1069 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1074 Session::set_play_range (bool yn)
1076 /* Called from event-processing context */
1078 if (_play_range != yn) {
1083 /* stop transport */
1084 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1088 ControlChanged (PlayRange); /* EMIT SIGNAL */
1093 Session::setup_auto_play ()
1095 /* Called from event-processing context */
1099 _clear_event_type (Event::RangeStop);
1100 _clear_event_type (Event::RangeLocate);
1106 list<AudioRange>::size_type sz = current_audio_range.size();
1110 list<AudioRange>::iterator i = current_audio_range.begin();
1111 list<AudioRange>::iterator next;
1113 while (i != current_audio_range.end()) {
1118 /* locating/stopping is subject to delays for declicking.
1121 jack_nframes_t requested_frame = (*i).end;
1123 if (requested_frame > current_block_size) {
1124 requested_frame -= current_block_size;
1126 requested_frame = 0;
1129 if (next == current_audio_range.end()) {
1130 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1132 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1140 } else if (sz == 1) {
1142 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1147 /* now start rolling at the right place */
1149 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1154 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1157 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1159 request_locate (start, true);
1163 Session::engine_halted ()
1165 /* there will be no more calls to process(), so
1166 we'd better clean up for ourselves, right now.
1168 but first, make sure the butler is out of
1172 g_atomic_int_set (&butler_should_do_transport_work, 0);
1173 post_transport_work = PostTransportWork (0);
1176 realtime_stop (false);
1177 non_realtime_stop (false);
1178 transport_sub_state = 0;
1180 TransportStateChange (); /* EMIT SIGNAL */
1185 Session::xrun_recovery ()
1187 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1189 HaltOnXrun (); /* EMIT SIGNAL */
1191 /* it didn't actually halt, but we need
1192 to handle things in the same way.
1200 Session::update_latency_compensation (bool with_stop, bool abort)
1202 bool update_jack = false;
1204 if (_state_of_the_state & Deletion) {
1208 Glib::RWLock::ReaderLock lm (route_lock);
1209 Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1210 _worst_track_latency = 0;
1212 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1214 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1215 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1218 jack_nframes_t old_latency = (*i)->signal_latency ();
1219 jack_nframes_t track_latency = (*i)->update_total_latency ();
1221 if (old_latency != track_latency) {
1225 if (!(*i)->hidden() && ((*i)->active())) {
1226 _worst_track_latency = max (_worst_track_latency, track_latency);
1230 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1231 (*i)->set_latency_delay (_worst_track_latency);
1234 /* tell JACK to play catch up */
1237 _engine.update_total_latencies ();
1240 set_worst_io_latencies (false);
1242 /* reflect any changes in latencies into capture offsets
1245 for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
1246 (*i)->set_capture_offset ();
1251 Session::update_latency_compensation_proxy (void* ignored)
1253 update_latency_compensation (false, false);