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.
24 #include <sigc++/bind.h>
25 #include <sigc++/retype.h>
28 #include <pbd/error.h>
29 #include <glibmm/thread.h>
30 #include <pbd/pthread_utils.h>
31 #include <pbd/memento_command.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 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
55 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
61 Session::request_slave_source (SlaveSource src)
63 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, 0, 0.0);
66 /* could set_seamless_loop() be disposed of entirely?*/
67 Config->set_seamless_loop (false);
69 Config->set_seamless_loop (true);
76 Session::request_transport_speed (float speed)
78 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
83 Session::request_diskstream_speed (Diskstream& ds, float speed)
85 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
91 Session::request_stop (bool abort)
93 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
98 Session::request_locate (nframes_t target_frame, bool with_roll)
100 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
105 Session::force_locate (nframes_t target_frame, bool with_roll)
107 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
112 Session::request_play_loop (bool yn)
115 Location *location = _locations.auto_loop_location();
117 if (location == 0 && yn) {
118 error << _("Cannot loop - no loop range defined")
123 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
126 if (!yn && Config->get_seamless_loop() && transport_rolling()) {
127 // request an immediate locate to refresh the diskstreams
128 // after disabling looping
129 request_locate (_transport_frame-1, false);
134 Session::realtime_stop (bool abort)
136 /* assume that when we start, we'll be moving forwards */
138 if (_transport_speed < 0.0f) {
139 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
141 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
144 if (actively_recording()) {
146 /* move the transport position back to where the
147 request for a stop was noticed. we rolled
148 past that point to pick up delayed input.
151 #ifndef LEAVE_TRANSPORT_UNADJUSTED
152 decrement_transport_position (_worst_output_latency);
155 /* the duration change is not guaranteed to have happened, but is likely */
157 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
161 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
164 _clear_event_type (Event::StopOnce);
165 _clear_event_type (Event::RangeStop);
166 _clear_event_type (Event::RangeLocate);
168 disable_record (true);
170 reset_slave_state ();
172 _transport_speed = 0;
174 if (Config->get_use_video_sync()) {
175 waiting_for_sync_offset = true;
178 transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0);
182 Session::butler_transport_work ()
186 boost::shared_ptr<RouteList> r = routes.reader ();
187 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
189 int on_entry = g_atomic_int_get (&butler_should_do_transport_work);
192 if (post_transport_work & PostTransportCurveRealloc) {
193 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
194 (*i)->curve_reallocate();
198 if (post_transport_work & PostTransportInputChange) {
199 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
200 (*i)->non_realtime_input_change ();
204 if (post_transport_work & PostTransportSpeed) {
205 non_realtime_set_speed ();
208 if (post_transport_work & PostTransportReverse) {
212 cumulative_rf_motion = 0;
215 /* don't seek if locate will take care of that in non_realtime_stop() */
217 if (!(post_transport_work & PostTransportLocate)) {
219 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
220 if (!(*i)->hidden()) {
221 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
222 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
225 (*i)->seek (_transport_frame);
228 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
229 /* new request, stop seeking, and start again */
230 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
237 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
238 non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
240 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
245 if (post_transport_work & PostTransportOverWrite) {
246 non_realtime_overwrite (on_entry, finished);
248 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
253 if (post_transport_work & PostTransportAudition) {
254 non_realtime_set_audition ();
257 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
261 Session::non_realtime_set_speed ()
263 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
265 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
266 (*i)->non_realtime_set_speed ();
271 Session::non_realtime_overwrite (int on_entry, bool& finished)
273 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
275 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
276 if ((*i)->pending_overwrite) {
277 (*i)->overwrite_existing_buffers ();
279 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
287 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
297 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
299 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
300 if ((*i)->get_captured_frames () != 0) {
306 /* stop and locate are merged here because they share a lot of common stuff */
309 now = localtime (&xnow);
312 auditioner->cancel_audition ();
316 cumulative_rf_motion = 0;
320 begin_reversible_command ("capture");
322 Location* loc = _locations.end_location();
323 bool change_end = false;
325 if (_transport_frame < loc->end()) {
327 /* stopped recording before current end */
329 if (_end_location_is_free) {
331 /* first capture for this session, move end back to where we are */
336 } else if (_transport_frame > loc->end()) {
338 /* stopped recording after the current end, extend it */
344 XMLNode &before = loc->get_state();
345 loc->set_end(_transport_frame);
346 XMLNode &after = loc->get_state();
347 add_command (new MementoCommand<Location>(*loc, &before, &after));
350 _end_location_is_free = false;
351 _have_captured = true;
354 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
355 (*i)->transport_stopped (*now, xnow, abort);
358 boost::shared_ptr<RouteList> r = routes.reader ();
360 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
361 if (!(*i)->hidden()) {
362 (*i)->set_pending_declick (0);
367 commit_reversible_command ();
370 if (_engine.running()) {
371 update_latency_compensation (true, abort);
374 if ((Config->get_slave_source() == None && Config->get_auto_return()) || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
376 if (pending_locate_flush) {
377 flush_all_redirects ();
380 if (((Config->get_slave_source() == None && Config->get_auto_return()) || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
382 _transport_frame = last_stop_frame;
384 if (synced_to_jack()) {
385 _engine.transport_locate (_transport_frame);
389 #ifndef LEAVE_TRANSPORT_UNADJUSTED
393 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
394 if (!(*i)->hidden()) {
395 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
396 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
399 (*i)->seek (_transport_frame);
402 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
404 /* we will be back */
408 #ifdef LEAVE_TRANSPORT_UNADJUSTED
412 last_stop_frame = _transport_frame;
414 send_full_time_code ();
415 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
416 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
420 /* XXX its a little odd that we're doing this here
421 when realtime_stop(), which has already executed,
425 if (!Config->get_latched_record_enable()) {
426 g_atomic_int_set (&_record_status, Disabled);
428 g_atomic_int_set (&_record_status, Enabled);
430 RecordStateChanged (); /* emit signal */
433 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
434 /* capture start has been changed, so save pending state */
435 save_state ("", true);
439 /* always try to get rid of this */
441 remove_pending_capture_state ();
443 /* save the current state of things if appropriate */
445 if (did_record && !saved) {
446 save_state (_current_snapshot_name);
449 if (post_transport_work & PostTransportDuration) {
450 DurationChanged (); /* EMIT SIGNAL */
453 if (post_transport_work & PostTransportStop) {
456 /* do not turn off autoloop on stop */
460 PositionChanged (_transport_frame); /* EMIT SIGNAL */
461 TransportStateChange (); /* EMIT SIGNAL */
463 /* and start it up again if relevant */
465 if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
466 request_transport_speed (1.0);
467 pending_locate_roll = false;
472 Session::check_declick_out ()
474 bool locate_required = transport_sub_state & PendingLocate;
476 /* this is called after a process() iteration. if PendingDeclickOut was set,
477 it means that we were waiting to declick the output (which has just been
478 done) before doing something else. this is where we do that "something else".
480 note: called from the audio thread.
483 if (transport_sub_state & PendingDeclickOut) {
485 if (locate_required) {
486 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
487 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
489 stop_transport (pending_abort);
490 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
496 Session::set_play_loop (bool yn)
498 /* Called from event-handling context */
500 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
506 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
507 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
508 "Recommend changing the configured options")
514 if ((play_loop = yn)) {
519 if ((loc = _locations.auto_loop_location()) != 0) {
521 if (Config->get_seamless_loop()) {
522 // set all diskstreams to use internal looping
523 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
524 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
525 if (!(*i)->hidden()) {
526 (*i)->set_loop (loc);
531 // set all diskstreams to NOT use internal looping
532 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
533 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
534 if (!(*i)->hidden()) {
540 /* stick in the loop event */
542 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
545 /* locate to start of loop and roll if current pos is outside of the loop range */
546 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
547 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
551 // locate to current position (+ 1 to force reload)
552 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
560 clear_events (Event::AutoLoop);
562 // set all diskstreams to NOT use internal looping
563 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
564 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
565 if (!(*i)->hidden()) {
574 Session::flush_all_redirects ()
576 boost::shared_ptr<RouteList> r = routes.reader ();
578 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
579 (*i)->flush_redirects ();
584 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
586 if (synced_to_jack()) {
591 _slave->speed_and_position (sp, pos);
593 if (target_frame != pos) {
595 /* tell JACK to change transport position, and we will
596 follow along later in ::follow_slave()
599 _engine.transport_locate (target_frame);
601 if (sp != 1.0f && with_roll) {
602 _engine.transport_start ();
609 locate (target_frame, with_roll, with_flush, with_loop);
614 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
616 if (actively_recording()) {
620 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
622 set_transport_speed (1.0, false);
624 loop_changing = false;
628 _transport_frame = target_frame;
630 if (_transport_speed && (!with_loop || loop_changing)) {
631 /* schedule a declick. we'll be called again when its done */
633 if (!(transport_sub_state & PendingDeclickOut)) {
634 transport_sub_state |= (PendingDeclickOut|PendingLocate);
635 pending_locate_frame = target_frame;
636 pending_locate_roll = with_roll;
637 pending_locate_flush = with_flush;
642 if (transport_rolling() && (!auto_play_legal || Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
643 realtime_stop (false);
646 if ( !with_loop || loop_changing) {
648 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
651 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
654 schedule_butler_transport_work ();
658 /* this is functionally what clear_clicks() does but with a tentative lock */
660 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
662 if (clickm.locked()) {
664 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
673 /* switch from input if we're going to roll */
674 if (Config->get_monitoring_model() == HardwareMonitoring) {
676 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
678 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
679 if ((*i)->record_enabled ()) {
680 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
681 (*i)->monitor_input (!Config->get_auto_input());
686 /* otherwise we're going to stop, so do the opposite */
687 if (Config->get_monitoring_model() == HardwareMonitoring) {
688 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
690 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
691 if ((*i)->record_enabled ()) {
692 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
693 (*i)->monitor_input (true);
699 /* cancel looped playback if transport pos outside of loop range */
701 Location* al = _locations.auto_loop_location();
703 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
704 // cancel looping directly, this is called from event handling context
705 set_play_loop (false);
709 loop_changing = false;
713 Session::set_transport_speed (float speed, bool abort)
715 if (_transport_speed == speed) {
720 speed = min (8.0f, speed);
721 } else if (speed < 0) {
722 speed = max (-8.0f, speed);
725 if (transport_rolling() && speed == 0.0) {
727 if (Config->get_monitoring_model() == HardwareMonitoring)
729 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
731 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
732 if ((*i)->record_enabled ()) {
733 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
734 (*i)->monitor_input (true);
739 if (synced_to_jack ()) {
740 _engine.transport_stop ();
742 stop_transport (abort);
745 } else if (transport_stopped() && speed == 1.0) {
747 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
751 if (Config->get_monitoring_model() == HardwareMonitoring) {
753 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
755 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
756 if (Config->get_auto_input() && (*i)->record_enabled ()) {
757 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
758 (*i)->monitor_input (false);
763 if (synced_to_jack()) {
764 _engine.transport_start ();
771 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
775 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
776 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
781 if (actively_recording()) {
785 if (speed > 0.0f && _transport_frame == current_end_frame()) {
789 if (speed < 0.0f && _transport_frame == 0) {
795 /* if we are reversing relative to the current speed, or relative to the speed
796 before the last stop, then we have to do extra work.
799 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
800 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
803 _last_transport_speed = _transport_speed;
804 _transport_speed = speed;
806 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
807 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
808 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
809 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
813 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
814 schedule_butler_transport_work ();
820 Session::stop_transport (bool abort)
822 if (_transport_speed == 0.0f) {
826 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
827 _worst_output_latency > current_block_size)
830 /* we need to capture the audio that has still not yet been received by the system
831 at the time the stop is requested, so we have to roll past that time.
833 we want to declick before stopping, so schedule the autostop for one
834 block before the actual end. we'll declick in the subsequent block,
835 and then we'll really be stopped.
838 Event *ev = new Event (Event::StopOnce, Event::Replace,
839 _transport_frame + _worst_output_latency - current_block_size,
843 transport_sub_state |= StopPendingCapture;
844 pending_abort = abort;
849 if ((transport_sub_state & PendingDeclickOut) == 0) {
850 transport_sub_state |= PendingDeclickOut;
851 /* we'll be called again after the declick */
852 pending_abort = abort;
856 realtime_stop (abort);
857 schedule_butler_transport_work ();
861 Session::start_transport ()
863 _last_roll_location = _transport_frame;
865 /* if record status is Enabled, move it to Recording. if its
866 already Recording, move it to Disabled.
869 switch (record_status()) {
871 if (!Config->get_punch_in()) {
877 disable_record (false);
884 if (!synced_to_jack() || _exporting) {
885 actually_start_transport ();
887 waiting_to_start = true;
892 Session::actually_start_transport ()
894 waiting_to_start = false;
896 transport_sub_state |= PendingDeclickIn;
897 _transport_speed = 1.0;
899 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
900 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
901 (*i)->realtime_set_speed ((*i)->speed(), true);
904 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
906 TransportStateChange (); /* EMIT SIGNAL */
910 Session::post_transport ()
912 if (post_transport_work & PostTransportAudition) {
913 if (auditioner && auditioner->active()) {
914 process_function = &Session::process_audition;
916 process_function = &Session::process_with_events;
920 if (post_transport_work & PostTransportStop) {
922 transport_sub_state = 0;
925 if (post_transport_work & PostTransportLocate) {
927 if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
931 transport_sub_state = 0;
937 post_transport_work = PostTransportWork (0);
941 Session::reset_rf_scale (nframes_t motion)
943 cumulative_rf_motion += motion;
945 if (cumulative_rf_motion < 4 * _current_frame_rate) {
947 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
949 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
961 Session::set_slave_source (SlaveSource src)
963 bool reverse = false;
964 bool non_rt_required = false;
966 if (_transport_speed) {
967 error << _("please stop the transport before adjusting slave settings") << endmsg;
971 // if (src == JACK && Config->get_jack_time_master()) {
980 if (_transport_speed < 0.0) {
992 _slave = new MTC_Slave (*this, *_mtc_port);
995 catch (failed_constructor& err) {
1000 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1003 _desired_transport_speed = _transport_speed;
1007 _slave = new JACK_Slave (_engine.jack());
1008 _desired_transport_speed = _transport_speed;
1012 Config->set_slave_source (src);
1014 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1015 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1016 if (!(*i)->hidden()) {
1017 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1018 non_rt_required = true;
1020 (*i)->set_slaved (_slave);
1025 reverse_diskstream_buffers ();
1028 if (non_rt_required) {
1029 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1030 schedule_butler_transport_work ();
1037 Session::reverse_diskstream_buffers ()
1039 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1040 schedule_butler_transport_work ();
1044 Session::set_diskstream_speed (Diskstream* stream, float speed)
1046 if (stream->realtime_set_speed (speed, false)) {
1047 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1048 schedule_butler_transport_work ();
1054 Session::set_audio_range (list<AudioRange>& range)
1056 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1057 ev->audio_range = range;
1062 Session::request_play_range (bool yn)
1064 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1069 Session::set_play_range (bool yn)
1071 /* Called from event-processing context */
1073 if (_play_range != yn) {
1078 /* stop transport */
1079 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1086 Session::setup_auto_play ()
1088 /* Called from event-processing context */
1092 _clear_event_type (Event::RangeStop);
1093 _clear_event_type (Event::RangeLocate);
1099 list<AudioRange>::size_type sz = current_audio_range.size();
1103 list<AudioRange>::iterator i = current_audio_range.begin();
1104 list<AudioRange>::iterator next;
1106 while (i != current_audio_range.end()) {
1111 /* locating/stopping is subject to delays for declicking.
1114 nframes_t requested_frame = (*i).end;
1116 if (requested_frame > current_block_size) {
1117 requested_frame -= current_block_size;
1119 requested_frame = 0;
1122 if (next == current_audio_range.end()) {
1123 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1125 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1133 } else if (sz == 1) {
1135 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1140 /* now start rolling at the right place */
1142 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1147 Session::request_bounded_roll (nframes_t start, nframes_t end)
1150 Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
1152 request_locate (start, true);
1156 Session::engine_halted ()
1160 /* there will be no more calls to process(), so
1161 we'd better clean up for ourselves, right now.
1163 but first, make sure the butler is out of
1167 g_atomic_int_set (&butler_should_do_transport_work, 0);
1168 post_transport_work = PostTransportWork (0);
1171 realtime_stop (false);
1172 non_realtime_stop (false, 0, ignored);
1173 transport_sub_state = 0;
1175 TransportStateChange (); /* EMIT SIGNAL */
1180 Session::xrun_recovery ()
1182 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1184 HaltOnXrun (); /* EMIT SIGNAL */
1186 /* it didn't actually halt, but we need
1187 to handle things in the same way.
1195 Session::update_latency_compensation (bool with_stop, bool abort)
1197 bool update_jack = false;
1199 if (_state_of_the_state & Deletion) {
1203 _worst_track_latency = 0;
1205 boost::shared_ptr<RouteList> r = routes.reader ();
1207 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1209 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1210 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1213 nframes_t old_latency = (*i)->signal_latency ();
1214 nframes_t track_latency = (*i)->update_total_latency ();
1216 if (old_latency != track_latency) {
1220 if (!(*i)->hidden() && ((*i)->active())) {
1221 _worst_track_latency = max (_worst_track_latency, track_latency);
1225 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1226 (*i)->set_latency_delay (_worst_track_latency);
1229 /* tell JACK to play catch up */
1232 _engine.update_total_latencies ();
1235 set_worst_io_latencies ();
1237 /* reflect any changes in latencies into capture offsets
1240 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1242 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1243 (*i)->set_capture_offset ();
1248 Session::update_latency_compensation_proxy (void* ignored)
1250 update_latency_compensation (false, false);
1254 Session::allow_auto_play (bool yn)
1256 auto_play_legal = yn;