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 if (_transport_speed < 0.0f) {
154 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
156 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
159 if (actively_recording()) {
161 /* move the transport position back to where the
162 request for a stop was noticed. we rolled
163 past that point to pick up delayed input.
166 #ifndef LEAVE_TRANSPORT_UNADJUSTED
167 decrement_transport_position (_worst_output_latency);
170 /* the duration change is not guaranteed to have happened, but is likely */
172 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
176 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
179 _clear_event_type (Event::StopOnce);
180 _clear_event_type (Event::RangeStop);
181 _clear_event_type (Event::RangeLocate);
183 disable_record (true);
185 reset_slave_state ();
187 _transport_speed = 0;
189 transport_sub_state = (auto_return ? AutoReturning : 0);
193 Session::butler_transport_work ()
195 Glib::RWLock::ReaderLock dsm (diskstream_lock);
196 boost::shared_ptr<RouteList> r = routes.reader ();
198 if (post_transport_work & PostTransportCurveRealloc) {
199 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
200 (*i)->curve_reallocate();
204 if (post_transport_work & PostTransportInputChange) {
205 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
206 (*i)->non_realtime_input_change ();
210 if (post_transport_work & PostTransportSpeed) {
211 non_realtime_set_speed ();
214 if (post_transport_work & PostTransportReverse) {
218 cumulative_rf_motion = 0;
221 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
222 if (!(*i)->hidden()) {
223 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
224 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
227 (*i)->seek (_transport_frame);
233 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
234 non_realtime_stop (post_transport_work & PostTransportAbort);
237 if (post_transport_work & PostTransportOverWrite) {
238 non_realtime_overwrite ();
241 if (post_transport_work & PostTransportAudition) {
242 non_realtime_set_audition ();
245 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
249 Session::non_realtime_set_speed ()
251 Glib::RWLock::ReaderLock lm (diskstream_lock);
253 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
254 (*i)->non_realtime_set_speed ();
259 Session::non_realtime_overwrite ()
261 Glib::RWLock::ReaderLock lm (diskstream_lock);
263 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
264 if ((*i)->pending_overwrite) {
265 (*i)->overwrite_existing_buffers ();
271 Session::non_realtime_stop (bool abort)
279 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
280 if ((*i)->get_captured_frames () != 0) {
286 /* stop and locate are merged here because they share a lot of common stuff */
289 now = localtime (&xnow);
292 auditioner->cancel_audition ();
296 cumulative_rf_motion = 0;
300 begin_reversible_command ("capture");
302 Location* loc = _locations.end_location();
303 bool change_end = false;
305 if (_transport_frame < loc->end()) {
307 /* stopped recording before current end */
309 if (_end_location_is_free) {
311 /* first capture for this session, move end back to where we are */
316 } else if (_transport_frame > loc->end()) {
318 /* stopped recording after the current end, extend it */
324 XMLNode &before = loc->get_state();
325 loc->set_end(_transport_frame);
326 XMLNode &after = loc->get_state();
327 add_command (new MementoCommand<Location>(*loc, &before, &after));
330 _end_location_is_free = false;
331 _have_captured = true;
334 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
335 (*i)->transport_stopped (*now, xnow, abort);
338 boost::shared_ptr<RouteList> r = routes.reader ();
340 for (RouteList::iterator i = r->begin(); i != r->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 (DiskstreamList::iterator i = diskstreams.begin(); i != 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);
384 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
386 #ifdef LEAVE_TRANSPORT_UNADJUSTED
390 last_stop_frame = _transport_frame;
392 send_full_time_code ();
393 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
394 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
398 /* XXX its a little odd that we're doing this here
399 when realtime_stop(), which has already executed,
403 if (!Config->get_latched_record_enable()) {
404 g_atomic_int_set (&_record_status, Disabled);
406 g_atomic_int_set (&_record_status, Enabled);
408 RecordStateChanged (); /* emit signal */
411 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
412 /* capture start has been changed, so save pending state */
413 save_state ("", true);
416 /* always try to get rid of this */
418 remove_pending_capture_state ();
420 /* save the current state of things if appropriate */
423 save_state (_current_snapshot_name);
426 if (post_transport_work & PostTransportDuration) {
427 DurationChanged (); /* EMIT SIGNAL */
430 if (post_transport_work & PostTransportStop) {
433 /* do not turn off autoloop on stop */
437 PositionChanged (_transport_frame); /* EMIT SIGNAL */
438 TransportStateChange (); /* EMIT SIGNAL */
440 /* and start it up again if relevant */
442 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
443 request_transport_speed (1.0);
444 pending_locate_roll = false;
449 Session::check_declick_out ()
451 bool locate_required = transport_sub_state & PendingLocate;
453 /* this is called after a process() iteration. if PendingDeclickOut was set,
454 it means that we were waiting to declick the output (which has just been
455 done) before doing something else. this is where we do that "something else".
457 note: called from the audio thread.
460 if (transport_sub_state & PendingDeclickOut) {
462 if (locate_required) {
463 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
464 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
466 stop_transport (pending_abort);
467 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
473 Session::set_auto_loop (bool yn)
475 /* Called from event-handling context */
477 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
483 if (yn && seamless_loop && synced_to_jack()) {
484 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
485 "Recommend changing the configured options")
491 if ((auto_loop = yn)) {
496 if ((loc = _locations.auto_loop_location()) != 0) {
499 // set all diskstreams to use internal looping
500 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
501 if (!(*i)->hidden()) {
502 (*i)->set_loop (loc);
507 // set all diskstreams to NOT use internal looping
508 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
509 if (!(*i)->hidden()) {
515 /* stick in the loop event */
517 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
520 /* locate to start of loop and roll if current pos is outside of the loop range */
521 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
522 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
526 // locate to current position (+ 1 to force reload)
527 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
535 clear_events (Event::AutoLoop);
537 // set all diskstreams to NOT use internal looping
538 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
539 if (!(*i)->hidden()) {
546 ControlChanged (AutoLoop); /* EMIT SIGNAL */
550 Session::flush_all_redirects ()
552 boost::shared_ptr<RouteList> r = routes.reader ();
554 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
555 (*i)->flush_redirects ();
560 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
562 if (synced_to_jack()) {
567 _slave->speed_and_position (sp, pos);
569 if (target_frame != pos) {
571 /* tell JACK to change transport position, and we will
572 follow along later in ::follow_slave()
575 _engine.transport_locate (target_frame);
577 if (sp != 1.0f && with_roll) {
578 _engine.transport_start ();
585 locate (target_frame, with_roll, with_flush, with_loop);
590 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
592 if (actively_recording()) {
596 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
598 set_transport_speed (1.0, false);
600 loop_changing = false;
604 _transport_frame = target_frame;
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 (DiskstreamList::iterator i = diskstreams.begin(); i != 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 (DiskstreamList::iterator i = diskstreams.begin(); i != 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;
694 Session::set_transport_speed (float speed, bool abort)
696 if (_transport_speed == speed) {
701 speed = min (8.0f, speed);
702 } else if (speed < 0) {
703 speed = max (-8.0f, speed);
706 if (transport_rolling() && speed == 0.0) {
708 if (Config->get_use_hardware_monitoring())
710 /* Even though this is called from RT context we are using
711 a non-tentative rwlock here, because the action must occur.
712 The rarity and short potential lock duration makes this "OK"
714 Glib::RWLock::ReaderLock dsm (diskstream_lock);
715 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
716 if ((*i)->record_enabled ()) {
717 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
718 (*i)->monitor_input (true);
723 if (synced_to_jack ()) {
724 _engine.transport_stop ();
726 stop_transport (abort);
729 } else if (transport_stopped() && speed == 1.0) {
731 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
735 if (Config->get_use_hardware_monitoring()) {
736 /* Even though this is called from RT context we are using
737 a non-tentative rwlock here, because the action must occur.
738 The rarity and short potential lock duration makes this "OK"
740 Glib::RWLock::ReaderLock dsm (diskstream_lock);
741 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
742 if (auto_input && (*i)->record_enabled ()) {
743 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
744 (*i)->monitor_input (false);
749 if (synced_to_jack()) {
750 _engine.transport_start ();
757 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
761 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
762 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
767 if (actively_recording()) {
771 if (speed > 0.0f && _transport_frame == current_end_frame()) {
775 if (speed < 0.0f && _transport_frame == 0) {
781 /* if we are reversing relative to the current speed, or relative to the speed
782 before the last stop, then we have to do extra work.
785 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
786 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
789 _last_transport_speed = _transport_speed;
790 _transport_speed = speed;
792 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
793 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
794 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
798 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
799 schedule_butler_transport_work ();
805 Session::stop_transport (bool abort)
807 if (_transport_speed == 0.0f) {
811 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
812 _worst_output_latency > current_block_size)
815 /* we need to capture the audio that has still not yet been received by the system
816 at the time the stop is requested, so we have to roll past that time.
818 we want to declick before stopping, so schedule the autostop for one
819 block before the actual end. we'll declick in the subsequent block,
820 and then we'll really be stopped.
823 Event *ev = new Event (Event::StopOnce, Event::Replace,
824 _transport_frame + _worst_output_latency - current_block_size,
828 transport_sub_state |= StopPendingCapture;
829 pending_abort = abort;
833 if ((transport_sub_state & PendingDeclickOut) == 0) {
834 transport_sub_state |= PendingDeclickOut;
835 /* we'll be called again after the declick */
839 realtime_stop (abort);
840 schedule_butler_transport_work ();
844 Session::start_transport ()
846 _last_roll_location = _transport_frame;
848 /* if record status is Enabled, move it to Recording. if its
849 already Recording, move it to Disabled.
852 switch (record_status()) {
860 disable_record (false);
867 if (!synced_to_jack() || _exporting) {
868 actually_start_transport ();
870 waiting_to_start = true;
875 Session::actually_start_transport ()
877 waiting_to_start = false;
879 transport_sub_state |= PendingDeclickIn;
880 _transport_speed = 1.0;
882 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
883 (*i)->realtime_set_speed ((*i)->speed(), true);
886 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
888 TransportStateChange (); /* EMIT SIGNAL */
892 Session::post_transport ()
894 if (post_transport_work & PostTransportAudition) {
895 if (auditioner && auditioner->active()) {
896 process_function = &Session::process_audition;
898 process_function = &Session::process_with_events;
902 if (post_transport_work & PostTransportStop) {
904 transport_sub_state = 0;
907 if (post_transport_work & PostTransportLocate) {
909 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
914 transport_sub_state = 0;
920 post_transport_work = PostTransportWork (0);
924 Session::set_rf_speed (float speed)
927 cumulative_rf_motion = 0;
932 Session::reset_rf_scale (jack_nframes_t motion)
934 cumulative_rf_motion += motion;
936 if (cumulative_rf_motion < 4 * _current_frame_rate) {
938 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
940 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
952 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
954 bool reverse = false;
955 bool non_rt_required = false;
957 if (src == _slave_type) {
961 if (_transport_speed) {
962 error << _("please stop the transport before adjusting slave settings") << endmsg;
963 /* help out non-MVC friendly UI's by telling them the slave type changed */
964 ControlChanged (SlaveType); /* EMIT SIGNAL */
968 // if (src == JACK && Config->get_jack_time_master()) {
978 if (_transport_speed < 0.0) {
990 _slave = new MTC_Slave (*this, *_mtc_port);
993 catch (failed_constructor& err) {
998 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1001 _desired_transport_speed = _transport_speed;
1005 _slave = new JACK_Slave (_engine.jack());
1006 _desired_transport_speed = _transport_speed;
1012 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1013 if (!(*i)->hidden()) {
1014 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1015 non_rt_required = true;
1017 (*i)->set_slaved (_slave);
1022 reverse_diskstream_buffers ();
1025 if (non_rt_required) {
1026 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1027 schedule_butler_transport_work ();
1031 ControlChanged (SlaveType); /* EMIT SIGNAL */
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);
1083 ControlChanged (PlayRange); /* EMIT SIGNAL */
1088 Session::setup_auto_play ()
1090 /* Called from event-processing context */
1094 _clear_event_type (Event::RangeStop);
1095 _clear_event_type (Event::RangeLocate);
1101 list<AudioRange>::size_type sz = current_audio_range.size();
1105 list<AudioRange>::iterator i = current_audio_range.begin();
1106 list<AudioRange>::iterator next;
1108 while (i != current_audio_range.end()) {
1113 /* locating/stopping is subject to delays for declicking.
1116 jack_nframes_t requested_frame = (*i).end;
1118 if (requested_frame > current_block_size) {
1119 requested_frame -= current_block_size;
1121 requested_frame = 0;
1124 if (next == current_audio_range.end()) {
1125 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1127 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1135 } else if (sz == 1) {
1137 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1142 /* now start rolling at the right place */
1144 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1149 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1152 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1154 request_locate (start, true);
1158 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);
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 Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1204 _worst_track_latency = 0;
1206 boost::shared_ptr<RouteList> r = routes.reader ();
1208 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1210 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1211 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1214 jack_nframes_t old_latency = (*i)->signal_latency ();
1215 jack_nframes_t track_latency = (*i)->update_total_latency ();
1217 if (old_latency != track_latency) {
1221 if (!(*i)->hidden() && ((*i)->active())) {
1222 _worst_track_latency = max (_worst_track_latency, track_latency);
1226 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1227 (*i)->set_latency_delay (_worst_track_latency);
1230 /* tell JACK to play catch up */
1233 _engine.update_total_latencies ();
1236 set_worst_io_latencies ();
1238 /* reflect any changes in latencies into capture offsets
1241 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1242 (*i)->set_capture_offset ();
1247 Session::update_latency_compensation_proxy (void* ignored)
1249 update_latency_compensation (false, false);