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 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
60 Session::request_slave_source (SlaveSource src, jack_nframes_t pos)
62 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, pos, 0.0);
64 if (src == Session::JACK) {
65 /* could set_seamless_loop() be disposed of entirely?*/
66 set_seamless_loop (false);
69 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 (jack_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 (jack_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_auto_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 && seamless_loop && transport_rolling()) {
127 // request an immediate locate to refresh the diskstreams
128 // after disabling looping
129 request_locate (_transport_frame-1, true);
134 Session::set_seamless_loop (bool yn)
136 if (seamless_loop != yn) {
139 if (auto_loop && transport_rolling()) {
140 // to reset diskstreams etc
141 request_auto_loop (true);
144 ControlChanged (SeamlessLoop); /* EMIT */
149 Session::realtime_stop (bool abort)
151 /* assume that when we start, we'll be moving forwards */
153 // FIXME: where should this really be? [DR]
154 //send_full_time_code();
155 deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
156 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
158 if (_transport_speed < 0.0f) {
159 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
161 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
164 if (actively_recording()) {
166 /* move the transport position back to where the
167 request for a stop was noticed. we rolled
168 past that point to pick up delayed input.
171 #ifndef LEAVE_TRANSPORT_UNADJUSTED
172 decrement_transport_position (_worst_output_latency);
175 /* the duration change is not guaranteed to have happened, but is likely */
177 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
181 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
184 _clear_event_type (Event::StopOnce);
185 _clear_event_type (Event::RangeStop);
186 _clear_event_type (Event::RangeLocate);
188 disable_record (true);
190 reset_slave_state ();
192 _transport_speed = 0;
194 transport_sub_state = (auto_return ? AutoReturning : 0);
198 Session::butler_transport_work ()
200 boost::shared_ptr<RouteList> r = routes.reader ();
201 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
203 if (post_transport_work & PostTransportCurveRealloc) {
204 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
205 (*i)->curve_reallocate();
209 if (post_transport_work & PostTransportInputChange) {
210 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
211 (*i)->non_realtime_input_change ();
215 if (post_transport_work & PostTransportSpeed) {
216 non_realtime_set_speed ();
219 if (post_transport_work & PostTransportReverse) {
223 cumulative_rf_motion = 0;
226 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
227 if (!(*i)->hidden()) {
228 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
229 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
232 (*i)->seek (_transport_frame);
238 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
239 non_realtime_stop (post_transport_work & PostTransportAbort);
242 if (post_transport_work & PostTransportOverWrite) {
243 non_realtime_overwrite ();
246 if (post_transport_work & PostTransportAudition) {
247 non_realtime_set_audition ();
250 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
254 Session::non_realtime_set_speed ()
256 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
258 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
259 (*i)->non_realtime_set_speed ();
264 Session::non_realtime_overwrite ()
266 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
268 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
269 if ((*i)->pending_overwrite) {
270 (*i)->overwrite_existing_buffers ();
276 Session::non_realtime_stop (bool abort)
284 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
286 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
287 if ((*i)->get_captured_frames () != 0) {
293 /* stop and locate are merged here because they share a lot of common stuff */
296 now = localtime (&xnow);
299 auditioner->cancel_audition ();
303 cumulative_rf_motion = 0;
307 begin_reversible_command ("capture");
309 Location* loc = _locations.end_location();
310 bool change_end = false;
312 if (_transport_frame < loc->end()) {
314 /* stopped recording before current end */
316 if (_end_location_is_free) {
318 /* first capture for this session, move end back to where we are */
323 } else if (_transport_frame > loc->end()) {
325 /* stopped recording after the current end, extend it */
331 XMLNode &before = loc->get_state();
332 loc->set_end(_transport_frame);
333 XMLNode &after = loc->get_state();
334 add_command (new MementoCommand<Location>(*loc, &before, &after));
337 _end_location_is_free = false;
338 _have_captured = true;
341 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
342 (*i)->transport_stopped (*now, xnow, abort);
345 boost::shared_ptr<RouteList> r = routes.reader ();
347 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
348 if (!(*i)->hidden()) {
349 (*i)->set_pending_declick (0);
354 commit_reversible_command ();
357 if (_engine.running()) {
358 update_latency_compensation (true, abort);
361 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
363 if (pending_locate_flush) {
364 flush_all_redirects ();
367 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
369 _transport_frame = last_stop_frame;
371 if (synced_to_jack()) {
372 _engine.transport_locate (_transport_frame);
376 #ifndef LEAVE_TRANSPORT_UNADJUSTED
380 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
381 if (!(*i)->hidden()) {
382 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
383 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
386 (*i)->seek (_transport_frame);
392 //deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
394 #ifdef LEAVE_TRANSPORT_UNADJUSTED
398 last_stop_frame = _transport_frame;
402 /* XXX its a little odd that we're doing this here
403 when realtime_stop(), which has already executed,
407 if (!Config->get_latched_record_enable()) {
408 g_atomic_int_set (&_record_status, Disabled);
410 g_atomic_int_set (&_record_status, Enabled);
412 RecordStateChanged (); /* emit signal */
415 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
416 /* capture start has been changed, so save pending state */
417 save_state ("", true);
420 /* always try to get rid of this */
422 remove_pending_capture_state ();
424 /* save the current state of things if appropriate */
427 save_state (_current_snapshot_name);
430 if (post_transport_work & PostTransportDuration) {
431 DurationChanged (); /* EMIT SIGNAL */
434 if (post_transport_work & PostTransportStop) {
437 /* do not turn off autoloop on stop */
441 PositionChanged (_transport_frame); /* EMIT SIGNAL */
442 TransportStateChange (); /* EMIT SIGNAL */
444 /* and start it up again if relevant */
446 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
447 request_transport_speed (1.0);
448 pending_locate_roll = false;
453 Session::check_declick_out ()
455 bool locate_required = transport_sub_state & PendingLocate;
457 /* this is called after a process() iteration. if PendingDeclickOut was set,
458 it means that we were waiting to declick the output (which has just been
459 done) before doing something else. this is where we do that "something else".
461 note: called from the audio thread.
464 if (transport_sub_state & PendingDeclickOut) {
466 if (locate_required) {
467 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
468 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
470 stop_transport (pending_abort);
471 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
477 Session::set_auto_loop (bool yn)
479 /* Called from event-handling context */
481 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
487 if (yn && seamless_loop && synced_to_jack()) {
488 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
489 "Recommend changing the configured options")
495 if ((auto_loop = yn)) {
500 if ((loc = _locations.auto_loop_location()) != 0) {
503 // set all diskstreams to use internal looping
504 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
505 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
506 if (!(*i)->hidden()) {
507 (*i)->set_loop (loc);
512 // set all diskstreams to NOT use internal looping
513 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
514 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
515 if (!(*i)->hidden()) {
521 /* stick in the loop event */
523 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
526 /* locate to start of loop and roll if current pos is outside of the loop range */
527 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
528 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
532 // locate to current position (+ 1 to force reload)
533 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
541 clear_events (Event::AutoLoop);
543 // set all diskstreams to NOT use internal looping
544 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
545 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
546 if (!(*i)->hidden()) {
553 ControlChanged (AutoLoop); /* EMIT SIGNAL */
557 Session::flush_all_redirects ()
559 boost::shared_ptr<RouteList> r = routes.reader ();
561 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
562 (*i)->flush_redirects ();
567 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
569 if (synced_to_jack()) {
574 _slave->speed_and_position (sp, pos);
576 if (target_frame != pos) {
578 /* tell JACK to change transport position, and we will
579 follow along later in ::follow_slave()
582 _engine.transport_locate (target_frame);
584 if (sp != 1.0f && with_roll) {
585 _engine.transport_start ();
592 locate (target_frame, with_roll, with_flush, with_loop);
597 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
599 if (actively_recording()) {
603 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
605 set_transport_speed (1.0, false);
607 loop_changing = false;
612 // [DR] FIXME: find out exactly where this should go below
613 _transport_frame = target_frame;
614 smpte_time(_transport_frame, transmitting_smpte_time);
615 outbound_mtc_smpte_frame = _transport_frame;
616 next_quarter_frame_to_send = 0;
618 if (_transport_speed && (!with_loop || loop_changing)) {
619 /* schedule a declick. we'll be called again when its done */
621 if (!(transport_sub_state & PendingDeclickOut)) {
622 transport_sub_state |= (PendingDeclickOut|PendingLocate);
623 pending_locate_frame = target_frame;
624 pending_locate_roll = with_roll;
625 pending_locate_flush = with_flush;
630 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
631 realtime_stop (false);
634 if ( !with_loop || loop_changing) {
636 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
639 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
642 schedule_butler_transport_work ();
646 /* this is functionally what clear_clicks() does but with a tentative lock */
648 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
650 if (clickm.locked()) {
652 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
661 /* switch from input if we're going to roll */
662 if (Config->get_use_hardware_monitoring()) {
664 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
666 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
667 if ((*i)->record_enabled ()) {
668 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
669 (*i)->monitor_input (!auto_input);
674 /* otherwise we're going to stop, so do the opposite */
675 if (Config->get_use_hardware_monitoring()) {
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 to input" << __FILE__ << __LINE__ << endl << endl;
681 (*i)->monitor_input (true);
687 /* cancel autoloop if transport pos outside of loop range */
689 Location* al = _locations.auto_loop_location();
691 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
692 // cancel looping directly, this is called from event handling context
693 set_auto_loop(false);
697 loop_changing = false;
699 _send_smpte_update = true;
703 Session::set_transport_speed (float speed, bool abort)
705 if (_transport_speed == speed) {
710 speed = min (8.0f, speed);
711 } else if (speed < 0) {
712 speed = max (-8.0f, speed);
715 if (transport_rolling() && speed == 0.0) {
717 if (Config->get_use_hardware_monitoring())
719 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
721 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
722 if ((*i)->record_enabled ()) {
723 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
724 (*i)->monitor_input (true);
729 if (synced_to_jack ()) {
730 _engine.transport_stop ();
732 stop_transport (abort);
735 } else if (transport_stopped() && speed == 1.0) {
737 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
741 if (Config->get_use_hardware_monitoring()) {
743 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
745 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
746 if (auto_input && (*i)->record_enabled ()) {
747 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
748 (*i)->monitor_input (false);
753 if (synced_to_jack()) {
754 _engine.transport_start ();
761 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
765 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
766 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
771 if (actively_recording()) {
775 if (speed > 0.0f && _transport_frame == current_end_frame()) {
779 if (speed < 0.0f && _transport_frame == 0) {
785 /* if we are reversing relative to the current speed, or relative to the speed
786 before the last stop, then we have to do extra work.
789 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
790 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
793 _last_transport_speed = _transport_speed;
794 _transport_speed = speed;
796 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
797 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
798 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
799 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
803 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
804 schedule_butler_transport_work ();
810 Session::stop_transport (bool abort)
812 if (_transport_speed == 0.0f) {
816 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
817 _worst_output_latency > current_block_size)
820 /* we need to capture the audio that has still not yet been received by the system
821 at the time the stop is requested, so we have to roll past that time.
823 we want to declick before stopping, so schedule the autostop for one
824 block before the actual end. we'll declick in the subsequent block,
825 and then we'll really be stopped.
828 Event *ev = new Event (Event::StopOnce, Event::Replace,
829 _transport_frame + _worst_output_latency - current_block_size,
833 transport_sub_state |= StopPendingCapture;
834 pending_abort = abort;
838 if ((transport_sub_state & PendingDeclickOut) == 0) {
839 transport_sub_state |= PendingDeclickOut;
840 /* we'll be called again after the declick */
844 realtime_stop (abort);
845 schedule_butler_transport_work ();
849 Session::start_transport ()
851 _last_roll_location = _transport_frame;
853 /* if record status is Enabled, move it to Recording. if its
854 already Recording, move it to Disabled.
857 switch (record_status()) {
865 disable_record (false);
872 if (!synced_to_jack() || _exporting) {
873 actually_start_transport ();
875 waiting_to_start = true;
880 Session::actually_start_transport ()
882 waiting_to_start = false;
884 transport_sub_state |= PendingDeclickIn;
885 _transport_speed = 1.0;
887 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
888 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
889 (*i)->realtime_set_speed ((*i)->speed(), true);
892 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
894 TransportStateChange (); /* EMIT SIGNAL */
897 /** Do any transport work in the audio thread that needs to be done after the
898 * transport thread is finished. Audio thread, realtime safe.
901 Session::post_transport ()
903 if (post_transport_work & PostTransportAudition) {
904 if (auditioner && auditioner->active()) {
905 process_function = &Session::process_audition;
907 process_function = &Session::process_with_events;
911 if (post_transport_work & PostTransportStop) {
913 transport_sub_state = 0;
916 if (post_transport_work & PostTransportLocate) {
918 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
923 transport_sub_state = 0;
929 post_transport_work = PostTransportWork (0);
933 Session::set_rf_speed (float speed)
936 cumulative_rf_motion = 0;
941 Session::reset_rf_scale (jack_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, jack_nframes_t frame)
963 bool reverse = false;
964 bool non_rt_required = false;
966 if (src == _slave_type) {
970 if (_transport_speed) {
971 error << _("please stop the transport before adjusting slave settings") << endmsg;
972 /* help out non-MVC friendly UI's by telling them the slave type changed */
973 ControlChanged (SlaveType); /* EMIT SIGNAL */
977 // if (src == JACK && Config->get_jack_time_master()) {
987 if (_transport_speed < 0.0) {
999 _slave = new MTC_Slave (*this, *_mtc_port);
1002 catch (failed_constructor& err) {
1007 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1010 _desired_transport_speed = _transport_speed;
1014 _slave = new JACK_Slave (_engine.jack());
1015 _desired_transport_speed = _transport_speed;
1021 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1022 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1023 if (!(*i)->hidden()) {
1024 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1025 non_rt_required = true;
1027 (*i)->set_slaved (_slave);
1032 reverse_diskstream_buffers ();
1035 if (non_rt_required) {
1036 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1037 schedule_butler_transport_work ();
1041 ControlChanged (SlaveType); /* EMIT SIGNAL */
1047 Session::reverse_diskstream_buffers ()
1049 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1050 schedule_butler_transport_work ();
1054 Session::set_diskstream_speed (Diskstream* stream, float speed)
1056 if (stream->realtime_set_speed (speed, false)) {
1057 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1058 schedule_butler_transport_work ();
1064 Session::set_audio_range (list<AudioRange>& range)
1066 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1067 ev->audio_range = range;
1072 Session::request_play_range (bool yn)
1074 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1079 Session::set_play_range (bool yn)
1081 /* Called from event-processing context */
1083 if (_play_range != yn) {
1088 /* stop transport */
1089 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1093 ControlChanged (PlayRange); /* EMIT SIGNAL */
1098 Session::setup_auto_play ()
1100 /* Called from event-processing context */
1104 _clear_event_type (Event::RangeStop);
1105 _clear_event_type (Event::RangeLocate);
1111 list<AudioRange>::size_type sz = current_audio_range.size();
1115 list<AudioRange>::iterator i = current_audio_range.begin();
1116 list<AudioRange>::iterator next;
1118 while (i != current_audio_range.end()) {
1123 /* locating/stopping is subject to delays for declicking.
1126 jack_nframes_t requested_frame = (*i).end;
1128 if (requested_frame > current_block_size) {
1129 requested_frame -= current_block_size;
1131 requested_frame = 0;
1134 if (next == current_audio_range.end()) {
1135 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1137 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1145 } else if (sz == 1) {
1147 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1152 /* now start rolling at the right place */
1154 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1159 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1162 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1164 request_locate (start, true);
1168 Session::engine_halted ()
1170 /* there will be no more calls to process(), so
1171 we'd better clean up for ourselves, right now.
1173 but first, make sure the butler is out of
1177 g_atomic_int_set (&butler_should_do_transport_work, 0);
1178 post_transport_work = PostTransportWork (0);
1181 realtime_stop (false);
1182 non_realtime_stop (false);
1183 transport_sub_state = 0;
1185 TransportStateChange (); /* EMIT SIGNAL */
1190 Session::xrun_recovery ()
1192 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1194 HaltOnXrun (); /* EMIT SIGNAL */
1196 /* it didn't actually halt, but we need
1197 to handle things in the same way.
1205 Session::update_latency_compensation (bool with_stop, bool abort)
1207 bool update_jack = false;
1209 if (_state_of_the_state & Deletion) {
1213 _worst_track_latency = 0;
1215 boost::shared_ptr<RouteList> r = routes.reader ();
1217 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1219 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1220 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1223 jack_nframes_t old_latency = (*i)->signal_latency ();
1224 jack_nframes_t track_latency = (*i)->update_total_latency ();
1226 if (old_latency != track_latency) {
1230 if (!(*i)->hidden() && ((*i)->active())) {
1231 _worst_track_latency = max (_worst_track_latency, track_latency);
1235 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1236 (*i)->set_latency_delay (_worst_track_latency);
1239 /* tell JACK to play catch up */
1242 _engine.update_total_latencies ();
1245 set_worst_io_latencies ();
1247 /* reflect any changes in latencies into capture offsets
1250 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1252 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1253 (*i)->set_capture_offset ();
1258 Session::update_latency_compensation_proxy (void* ignored)
1260 update_latency_compensation (false, false);