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>
32 #include <pbd/memento_command.h>
34 #include <midi++/mmc.h>
35 #include <midi++/port.h>
37 #include <ardour/ardour.h>
38 #include <ardour/audioengine.h>
39 #include <ardour/session.h>
40 #include <ardour/audio_diskstream.h>
41 #include <ardour/auditioner.h>
42 #include <ardour/slave.h>
43 #include <ardour/location.h>
48 using namespace ARDOUR;
53 Session::request_input_change_handling ()
55 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
56 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
62 Session::request_slave_source (SlaveSource src)
64 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, 0, 0.0);
67 /* could set_seamless_loop() be disposed of entirely?*/
68 Config->set_seamless_loop (false);
70 Config->set_seamless_loop (true);
77 Session::request_transport_speed (float speed)
79 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
84 Session::request_diskstream_speed (Diskstream& ds, float speed)
86 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
92 Session::request_stop (bool abort)
94 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
99 Session::request_locate (nframes_t target_frame, bool with_roll)
101 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
106 Session::force_locate (nframes_t target_frame, bool with_roll)
108 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
113 Session::request_play_loop (bool yn)
116 Location *location = _locations.auto_loop_location();
118 if (location == 0 && yn) {
119 error << _("Cannot loop - no loop range defined")
124 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
127 if (!yn && Config->get_seamless_loop() && transport_rolling()) {
128 // request an immediate locate to refresh the diskstreams
129 // after disabling looping
130 request_locate (_transport_frame-1, false);
135 Session::realtime_stop (bool abort)
137 /* assume that when we start, we'll be moving forwards */
139 if (_transport_speed < 0.0f) {
140 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
142 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
145 if (actively_recording()) {
147 /* move the transport position back to where the
148 request for a stop was noticed. we rolled
149 past that point to pick up delayed input.
152 #ifndef LEAVE_TRANSPORT_UNADJUSTED
153 decrement_transport_position (_worst_output_latency);
156 /* the duration change is not guaranteed to have happened, but is likely */
158 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
162 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
165 _clear_event_type (Event::StopOnce);
166 _clear_event_type (Event::RangeStop);
167 _clear_event_type (Event::RangeLocate);
169 disable_record (true);
171 reset_slave_state ();
173 _transport_speed = 0;
175 if (Config->get_use_video_sync()) {
176 waiting_for_sync_offset = true;
179 transport_sub_state = (Config->get_auto_return() ? AutoReturning : 0);
183 Session::butler_transport_work ()
187 boost::shared_ptr<RouteList> r = routes.reader ();
188 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
190 int on_entry = g_atomic_int_get (&butler_should_do_transport_work);
193 if (post_transport_work & PostTransportCurveRealloc) {
194 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
195 (*i)->curve_reallocate();
199 if (post_transport_work & PostTransportInputChange) {
200 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
201 (*i)->non_realtime_input_change ();
205 if (post_transport_work & PostTransportSpeed) {
206 non_realtime_set_speed ();
209 if (post_transport_work & PostTransportReverse) {
213 cumulative_rf_motion = 0;
216 /* don't seek if locate will take care of that in non_realtime_stop() */
218 if (!(post_transport_work & PostTransportLocate)) {
220 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
221 if (!(*i)->hidden()) {
222 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
223 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
226 (*i)->seek (_transport_frame);
229 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
230 /* new request, stop seeking, and start again */
231 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
238 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
239 non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
241 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
246 if (post_transport_work & PostTransportOverWrite) {
247 non_realtime_overwrite (on_entry, finished);
249 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
254 if (post_transport_work & PostTransportAudition) {
255 non_realtime_set_audition ();
258 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
262 Session::non_realtime_set_speed ()
264 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
266 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
267 (*i)->non_realtime_set_speed ();
272 Session::non_realtime_overwrite (int on_entry, bool& finished)
274 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
276 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
277 if ((*i)->pending_overwrite) {
278 (*i)->overwrite_existing_buffers ();
280 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
288 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
298 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
300 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
301 if ((*i)->get_captured_frames () != 0) {
307 /* stop and locate are merged here because they share a lot of common stuff */
310 now = localtime (&xnow);
313 auditioner->cancel_audition ();
317 cumulative_rf_motion = 0;
321 begin_reversible_command ("capture");
323 Location* loc = _locations.end_location();
324 bool change_end = false;
326 if (_transport_frame < loc->end()) {
328 /* stopped recording before current end */
330 if (_end_location_is_free) {
332 /* first capture for this session, move end back to where we are */
337 } else if (_transport_frame > loc->end()) {
339 /* stopped recording after the current end, extend it */
345 XMLNode &before = loc->get_state();
346 loc->set_end(_transport_frame);
347 XMLNode &after = loc->get_state();
348 add_command (new MementoCommand<Location>(*loc, &before, &after));
351 _end_location_is_free = false;
352 _have_captured = true;
355 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
356 (*i)->transport_stopped (*now, xnow, abort);
359 boost::shared_ptr<RouteList> r = routes.reader ();
361 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
362 if (!(*i)->hidden()) {
363 (*i)->set_pending_declick (0);
368 commit_reversible_command ();
371 if (_engine.running()) {
372 update_latency_compensation (true, abort);
375 if (Config->get_auto_return() || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
377 if (pending_locate_flush) {
378 flush_all_redirects ();
381 if ((Config->get_auto_return() || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
383 _transport_frame = last_stop_frame;
385 if (synced_to_jack()) {
386 _engine.transport_locate (_transport_frame);
390 #ifndef LEAVE_TRANSPORT_UNADJUSTED
394 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
395 if (!(*i)->hidden()) {
396 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
397 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
400 (*i)->seek (_transport_frame);
403 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
405 /* we will be back */
409 #ifdef LEAVE_TRANSPORT_UNADJUSTED
413 last_stop_frame = _transport_frame;
415 send_full_time_code ();
416 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
417 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
421 /* XXX its a little odd that we're doing this here
422 when realtime_stop(), which has already executed,
426 if (!Config->get_latched_record_enable()) {
427 g_atomic_int_set (&_record_status, Disabled);
429 g_atomic_int_set (&_record_status, Enabled);
431 RecordStateChanged (); /* emit signal */
434 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
435 /* capture start has been changed, so save pending state */
436 save_state ("", true);
440 /* always try to get rid of this */
442 remove_pending_capture_state ();
444 /* save the current state of things if appropriate */
446 if (did_record && !saved) {
447 save_state (_current_snapshot_name);
450 if (post_transport_work & PostTransportDuration) {
451 DurationChanged (); /* EMIT SIGNAL */
454 if (post_transport_work & PostTransportStop) {
457 /* do not turn off autoloop on stop */
461 PositionChanged (_transport_frame); /* EMIT SIGNAL */
462 TransportStateChange (); /* EMIT SIGNAL */
464 /* and start it up again if relevant */
466 if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
467 request_transport_speed (1.0);
468 pending_locate_roll = false;
473 Session::check_declick_out ()
475 bool locate_required = transport_sub_state & PendingLocate;
477 /* this is called after a process() iteration. if PendingDeclickOut was set,
478 it means that we were waiting to declick the output (which has just been
479 done) before doing something else. this is where we do that "something else".
481 note: called from the audio thread.
484 if (transport_sub_state & PendingDeclickOut) {
486 if (locate_required) {
487 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
488 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
490 stop_transport (pending_abort);
491 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
497 Session::set_play_loop (bool yn)
499 /* Called from event-handling context */
501 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
507 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
508 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
509 "Recommend changing the configured options")
515 if ((play_loop = yn)) {
520 if ((loc = _locations.auto_loop_location()) != 0) {
522 if (Config->get_seamless_loop()) {
523 // set all diskstreams to use internal looping
524 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
525 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
526 if (!(*i)->hidden()) {
527 (*i)->set_loop (loc);
532 // set all diskstreams to NOT use internal looping
533 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
534 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
535 if (!(*i)->hidden()) {
541 /* stick in the loop event */
543 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
546 /* locate to start of loop and roll if current pos is outside of the loop range */
547 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
548 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
552 // locate to current position (+ 1 to force reload)
553 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
561 clear_events (Event::AutoLoop);
563 // set all diskstreams to NOT use internal looping
564 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
565 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
566 if (!(*i)->hidden()) {
575 Session::flush_all_redirects ()
577 boost::shared_ptr<RouteList> r = routes.reader ();
579 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
580 (*i)->flush_redirects ();
585 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
587 if (synced_to_jack()) {
592 _slave->speed_and_position (sp, pos);
594 if (target_frame != pos) {
596 /* tell JACK to change transport position, and we will
597 follow along later in ::follow_slave()
600 _engine.transport_locate (target_frame);
602 if (sp != 1.0f && with_roll) {
603 _engine.transport_start ();
610 locate (target_frame, with_roll, with_flush, with_loop);
615 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
617 if (actively_recording()) {
621 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
623 set_transport_speed (1.0, false);
625 loop_changing = false;
629 _transport_frame = target_frame;
631 if (_transport_speed && (!with_loop || loop_changing)) {
632 /* schedule a declick. we'll be called again when its done */
634 if (!(transport_sub_state & PendingDeclickOut)) {
635 transport_sub_state |= (PendingDeclickOut|PendingLocate);
636 pending_locate_frame = target_frame;
637 pending_locate_roll = with_roll;
638 pending_locate_flush = with_flush;
643 if (transport_rolling() && !Config->get_auto_play() && !with_roll && !(synced_to_jack() && play_loop)) {
644 realtime_stop (false);
647 if ( !with_loop || loop_changing) {
649 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
652 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
655 schedule_butler_transport_work ();
659 cerr << "butler not requested\n";
661 /* this is functionally what clear_clicks() does but with a tentative lock */
663 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
665 if (clickm.locked()) {
667 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
676 /* switch from input if we're going to roll */
677 if (Config->get_monitoring_model() == HardwareMonitoring) {
679 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
681 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
682 if ((*i)->record_enabled ()) {
683 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
684 (*i)->monitor_input (!Config->get_auto_input());
689 /* otherwise we're going to stop, so do the opposite */
690 if (Config->get_monitoring_model() == HardwareMonitoring) {
691 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
693 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
694 if ((*i)->record_enabled ()) {
695 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
696 (*i)->monitor_input (true);
702 /* cancel looped playback if transport pos outside of loop range */
704 Location* al = _locations.auto_loop_location();
706 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
707 // cancel looping directly, this is called from event handling context
708 set_play_loop (false);
712 loop_changing = false;
716 Session::set_transport_speed (float speed, bool abort)
718 if (_transport_speed == speed) {
723 speed = min (8.0f, speed);
724 } else if (speed < 0) {
725 speed = max (-8.0f, speed);
728 if (transport_rolling() && speed == 0.0) {
730 if (Config->get_monitoring_model() == HardwareMonitoring)
732 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
734 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
735 if ((*i)->record_enabled ()) {
736 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
737 (*i)->monitor_input (true);
742 if (synced_to_jack ()) {
743 _engine.transport_stop ();
745 stop_transport (abort);
748 } else if (transport_stopped() && speed == 1.0) {
750 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
754 if (Config->get_monitoring_model() == HardwareMonitoring) {
756 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
758 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
759 if (Config->get_auto_input() && (*i)->record_enabled ()) {
760 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
761 (*i)->monitor_input (false);
766 if (synced_to_jack()) {
767 _engine.transport_start ();
774 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
778 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
779 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
784 if (actively_recording()) {
788 if (speed > 0.0f && _transport_frame == current_end_frame()) {
792 if (speed < 0.0f && _transport_frame == 0) {
798 /* if we are reversing relative to the current speed, or relative to the speed
799 before the last stop, then we have to do extra work.
802 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
803 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
806 _last_transport_speed = _transport_speed;
807 _transport_speed = speed;
809 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
810 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
811 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
812 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
816 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
817 schedule_butler_transport_work ();
823 Session::stop_transport (bool abort)
825 if (_transport_speed == 0.0f) {
829 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
830 _worst_output_latency > current_block_size)
833 /* we need to capture the audio that has still not yet been received by the system
834 at the time the stop is requested, so we have to roll past that time.
836 we want to declick before stopping, so schedule the autostop for one
837 block before the actual end. we'll declick in the subsequent block,
838 and then we'll really be stopped.
841 Event *ev = new Event (Event::StopOnce, Event::Replace,
842 _transport_frame + _worst_output_latency - current_block_size,
846 transport_sub_state |= StopPendingCapture;
847 pending_abort = abort;
852 if ((transport_sub_state & PendingDeclickOut) == 0) {
853 transport_sub_state |= PendingDeclickOut;
854 /* we'll be called again after the declick */
855 pending_abort = abort;
859 realtime_stop (abort);
860 schedule_butler_transport_work ();
864 Session::start_transport ()
866 _last_roll_location = _transport_frame;
868 /* if record status is Enabled, move it to Recording. if its
869 already Recording, move it to Disabled.
872 switch (record_status()) {
874 if (!Config->get_punch_in()) {
880 disable_record (false);
887 if (!synced_to_jack() || _exporting) {
888 actually_start_transport ();
890 waiting_to_start = true;
895 Session::actually_start_transport ()
897 waiting_to_start = false;
899 transport_sub_state |= PendingDeclickIn;
900 _transport_speed = 1.0;
902 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
903 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
904 (*i)->realtime_set_speed ((*i)->speed(), true);
907 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
909 TransportStateChange (); /* EMIT SIGNAL */
913 Session::post_transport ()
915 if (post_transport_work & PostTransportAudition) {
916 if (auditioner && auditioner->active()) {
917 process_function = &Session::process_audition;
919 process_function = &Session::process_with_events;
923 if (post_transport_work & PostTransportStop) {
925 transport_sub_state = 0;
928 if (post_transport_work & PostTransportLocate) {
930 if ((Config->get_auto_play() && !_exporting) || (post_transport_work & PostTransportRoll)) {
934 transport_sub_state = 0;
940 post_transport_work = PostTransportWork (0);
944 Session::reset_rf_scale (nframes_t motion)
946 cumulative_rf_motion += motion;
948 if (cumulative_rf_motion < 4 * _current_frame_rate) {
950 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
952 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
964 Session::set_slave_source (SlaveSource src)
966 bool reverse = false;
967 bool non_rt_required = false;
969 if (_transport_speed) {
970 error << _("please stop the transport before adjusting slave settings") << endmsg;
974 // 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;
1015 Config->set_slave_source (src);
1017 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1018 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1019 if (!(*i)->hidden()) {
1020 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1021 non_rt_required = true;
1023 (*i)->set_slaved (_slave);
1028 reverse_diskstream_buffers ();
1031 if (non_rt_required) {
1032 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1033 schedule_butler_transport_work ();
1040 Session::reverse_diskstream_buffers ()
1042 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1043 schedule_butler_transport_work ();
1047 Session::set_diskstream_speed (Diskstream* stream, float speed)
1049 if (stream->realtime_set_speed (speed, false)) {
1050 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1051 schedule_butler_transport_work ();
1057 Session::set_audio_range (list<AudioRange>& range)
1059 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1060 ev->audio_range = range;
1065 Session::request_play_range (bool yn)
1067 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1072 Session::set_play_range (bool yn)
1074 /* Called from event-processing context */
1076 if (_play_range != yn) {
1081 /* stop transport */
1082 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1089 Session::setup_auto_play ()
1091 /* Called from event-processing context */
1095 _clear_event_type (Event::RangeStop);
1096 _clear_event_type (Event::RangeLocate);
1102 list<AudioRange>::size_type sz = current_audio_range.size();
1106 list<AudioRange>::iterator i = current_audio_range.begin();
1107 list<AudioRange>::iterator next;
1109 while (i != current_audio_range.end()) {
1114 /* locating/stopping is subject to delays for declicking.
1117 nframes_t requested_frame = (*i).end;
1119 if (requested_frame > current_block_size) {
1120 requested_frame -= current_block_size;
1122 requested_frame = 0;
1125 if (next == current_audio_range.end()) {
1126 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1128 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1136 } else if (sz == 1) {
1138 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1143 /* now start rolling at the right place */
1145 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1150 Session::request_bounded_roll (nframes_t start, nframes_t end)
1153 Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
1155 request_locate (start, true);
1159 Session::engine_halted ()
1163 /* there will be no more calls to process(), so
1164 we'd better clean up for ourselves, right now.
1166 but first, make sure the butler is out of
1170 g_atomic_int_set (&butler_should_do_transport_work, 0);
1171 post_transport_work = PostTransportWork (0);
1174 realtime_stop (false);
1175 non_realtime_stop (false, 0, ignored);
1176 transport_sub_state = 0;
1178 TransportStateChange (); /* EMIT SIGNAL */
1183 Session::xrun_recovery ()
1185 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1187 HaltOnXrun (); /* EMIT SIGNAL */
1189 /* it didn't actually halt, but we need
1190 to handle things in the same way.
1198 Session::update_latency_compensation (bool with_stop, bool abort)
1200 bool update_jack = false;
1202 if (_state_of_the_state & Deletion) {
1206 _worst_track_latency = 0;
1208 boost::shared_ptr<RouteList> r = routes.reader ();
1210 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1212 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1213 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1216 nframes_t old_latency = (*i)->signal_latency ();
1217 nframes_t track_latency = (*i)->update_total_latency ();
1219 if (old_latency != track_latency) {
1223 if (!(*i)->hidden() && ((*i)->active())) {
1224 _worst_track_latency = max (_worst_track_latency, track_latency);
1228 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1229 (*i)->set_latency_delay (_worst_track_latency);
1232 /* tell JACK to play catch up */
1235 _engine.update_total_latencies ();
1238 set_worst_io_latencies ();
1240 /* reflect any changes in latencies into capture offsets
1243 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1245 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1246 (*i)->set_capture_offset ();
1251 Session::update_latency_compensation_proxy (void* ignored)
1253 update_latency_compensation (false, false);