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 if (Config->get_use_video_sync()) {
195 waiting_for_sync_offset = true;
198 transport_sub_state = (auto_return ? AutoReturning : 0);
202 Session::butler_transport_work ()
204 boost::shared_ptr<RouteList> r = routes.reader ();
205 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
207 if (post_transport_work & PostTransportCurveRealloc) {
208 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
209 (*i)->curve_reallocate();
213 if (post_transport_work & PostTransportInputChange) {
214 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
215 (*i)->non_realtime_input_change ();
219 if (post_transport_work & PostTransportSpeed) {
220 non_realtime_set_speed ();
223 if (post_transport_work & PostTransportReverse) {
227 cumulative_rf_motion = 0;
230 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
231 if (!(*i)->hidden()) {
232 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
233 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
236 (*i)->seek (_transport_frame);
242 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
243 non_realtime_stop (post_transport_work & PostTransportAbort);
246 if (post_transport_work & PostTransportOverWrite) {
247 non_realtime_overwrite ();
250 if (post_transport_work & PostTransportAudition) {
251 non_realtime_set_audition ();
254 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
258 Session::non_realtime_set_speed ()
260 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
262 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
263 (*i)->non_realtime_set_speed ();
268 Session::non_realtime_overwrite ()
270 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
272 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
273 if ((*i)->pending_overwrite) {
274 (*i)->overwrite_existing_buffers ();
280 Session::non_realtime_stop (bool abort)
288 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
290 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
291 if ((*i)->get_captured_frames () != 0) {
297 /* stop and locate are merged here because they share a lot of common stuff */
300 now = localtime (&xnow);
303 auditioner->cancel_audition ();
307 cumulative_rf_motion = 0;
311 begin_reversible_command ("capture");
313 Location* loc = _locations.end_location();
314 bool change_end = false;
316 if (_transport_frame < loc->end()) {
318 /* stopped recording before current end */
320 if (_end_location_is_free) {
322 /* first capture for this session, move end back to where we are */
327 } else if (_transport_frame > loc->end()) {
329 /* stopped recording after the current end, extend it */
335 XMLNode &before = loc->get_state();
336 loc->set_end(_transport_frame);
337 XMLNode &after = loc->get_state();
338 add_command (new MementoCommand<Location>(*loc, &before, &after));
341 _end_location_is_free = false;
342 _have_captured = true;
345 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
346 (*i)->transport_stopped (*now, xnow, abort);
349 boost::shared_ptr<RouteList> r = routes.reader ();
351 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
352 if (!(*i)->hidden()) {
353 (*i)->set_pending_declick (0);
358 commit_reversible_command ();
361 if (_engine.running()) {
362 update_latency_compensation (true, abort);
365 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
367 if (pending_locate_flush) {
368 flush_all_redirects ();
371 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
373 _transport_frame = last_stop_frame;
375 if (synced_to_jack()) {
376 _engine.transport_locate (_transport_frame);
380 #ifndef LEAVE_TRANSPORT_UNADJUSTED
384 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
385 if (!(*i)->hidden()) {
386 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
387 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
390 (*i)->seek (_transport_frame);
396 //deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
398 #ifdef LEAVE_TRANSPORT_UNADJUSTED
402 last_stop_frame = _transport_frame;
406 /* XXX its a little odd that we're doing this here
407 when realtime_stop(), which has already executed,
411 if (!Config->get_latched_record_enable()) {
412 g_atomic_int_set (&_record_status, Disabled);
414 g_atomic_int_set (&_record_status, Enabled);
416 RecordStateChanged (); /* emit signal */
419 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
420 /* capture start has been changed, so save pending state */
421 save_state ("", true);
424 /* always try to get rid of this */
426 remove_pending_capture_state ();
428 /* save the current state of things if appropriate */
431 save_state (_current_snapshot_name);
434 if (post_transport_work & PostTransportDuration) {
435 DurationChanged (); /* EMIT SIGNAL */
438 if (post_transport_work & PostTransportStop) {
441 /* do not turn off autoloop on stop */
445 PositionChanged (_transport_frame); /* EMIT SIGNAL */
446 TransportStateChange (); /* EMIT SIGNAL */
448 /* and start it up again if relevant */
450 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
451 request_transport_speed (1.0);
452 pending_locate_roll = false;
457 Session::check_declick_out ()
459 bool locate_required = transport_sub_state & PendingLocate;
461 /* this is called after a process() iteration. if PendingDeclickOut was set,
462 it means that we were waiting to declick the output (which has just been
463 done) before doing something else. this is where we do that "something else".
465 note: called from the audio thread.
468 if (transport_sub_state & PendingDeclickOut) {
470 if (locate_required) {
471 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
472 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
474 stop_transport (pending_abort);
475 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
481 Session::set_auto_loop (bool yn)
483 /* Called from event-handling context */
485 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
491 if (yn && seamless_loop && synced_to_jack()) {
492 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
493 "Recommend changing the configured options")
499 if ((auto_loop = yn)) {
504 if ((loc = _locations.auto_loop_location()) != 0) {
507 // set all diskstreams to use internal looping
508 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
509 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
510 if (!(*i)->hidden()) {
511 (*i)->set_loop (loc);
516 // set all diskstreams to NOT use internal looping
517 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
518 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
519 if (!(*i)->hidden()) {
525 /* stick in the loop event */
527 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
530 /* locate to start of loop and roll if current pos is outside of the loop range */
531 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
532 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
536 // locate to current position (+ 1 to force reload)
537 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
545 clear_events (Event::AutoLoop);
547 // set all diskstreams to NOT use internal looping
548 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
549 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
550 if (!(*i)->hidden()) {
557 ControlChanged (AutoLoop); /* EMIT SIGNAL */
561 Session::flush_all_redirects ()
563 boost::shared_ptr<RouteList> r = routes.reader ();
565 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
566 (*i)->flush_redirects ();
571 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
573 if (synced_to_jack()) {
578 _slave->speed_and_position (sp, pos);
580 if (target_frame != pos) {
582 /* tell JACK to change transport position, and we will
583 follow along later in ::follow_slave()
586 _engine.transport_locate (target_frame);
588 if (sp != 1.0f && with_roll) {
589 _engine.transport_start ();
596 locate (target_frame, with_roll, with_flush, with_loop);
601 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
603 if (actively_recording()) {
607 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
609 set_transport_speed (1.0, false);
611 loop_changing = false;
616 // [DR] FIXME: find out exactly where this should go below
617 _transport_frame = target_frame;
618 smpte_time(_transport_frame, transmitting_smpte_time);
619 outbound_mtc_smpte_frame = _transport_frame;
620 next_quarter_frame_to_send = 0;
622 if (_transport_speed && (!with_loop || loop_changing)) {
623 /* schedule a declick. we'll be called again when its done */
625 if (!(transport_sub_state & PendingDeclickOut)) {
626 transport_sub_state |= (PendingDeclickOut|PendingLocate);
627 pending_locate_frame = target_frame;
628 pending_locate_roll = with_roll;
629 pending_locate_flush = with_flush;
634 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
635 realtime_stop (false);
638 if ( !with_loop || loop_changing) {
640 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
643 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
646 schedule_butler_transport_work ();
650 /* this is functionally what clear_clicks() does but with a tentative lock */
652 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
654 if (clickm.locked()) {
656 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
665 /* switch from input if we're going to roll */
666 if (Config->get_use_hardware_monitoring()) {
668 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
670 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
671 if ((*i)->record_enabled ()) {
672 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
673 (*i)->monitor_input (!auto_input);
678 /* otherwise we're going to stop, so do the opposite */
679 if (Config->get_use_hardware_monitoring()) {
680 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
682 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
683 if ((*i)->record_enabled ()) {
684 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
685 (*i)->monitor_input (true);
691 /* cancel autoloop if transport pos outside of loop range */
693 Location* al = _locations.auto_loop_location();
695 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
696 // cancel looping directly, this is called from event handling context
697 set_auto_loop(false);
701 loop_changing = false;
703 _send_smpte_update = true;
707 Session::set_transport_speed (float speed, bool abort)
709 if (_transport_speed == speed) {
714 speed = min (8.0f, speed);
715 } else if (speed < 0) {
716 speed = max (-8.0f, speed);
719 if (transport_rolling() && speed == 0.0) {
721 if (Config->get_use_hardware_monitoring())
723 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
725 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
726 if ((*i)->record_enabled ()) {
727 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
728 (*i)->monitor_input (true);
733 if (synced_to_jack ()) {
734 _engine.transport_stop ();
736 stop_transport (abort);
739 } else if (transport_stopped() && speed == 1.0) {
741 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
745 if (Config->get_use_hardware_monitoring()) {
747 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
749 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
750 if (auto_input && (*i)->record_enabled ()) {
751 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
752 (*i)->monitor_input (false);
757 if (synced_to_jack()) {
758 _engine.transport_start ();
765 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
769 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
770 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
775 if (actively_recording()) {
779 if (speed > 0.0f && _transport_frame == current_end_frame()) {
783 if (speed < 0.0f && _transport_frame == 0) {
789 /* if we are reversing relative to the current speed, or relative to the speed
790 before the last stop, then we have to do extra work.
793 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
794 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
797 _last_transport_speed = _transport_speed;
798 _transport_speed = speed;
800 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
801 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
802 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
803 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
807 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
808 schedule_butler_transport_work ();
814 Session::stop_transport (bool abort)
816 if (_transport_speed == 0.0f) {
820 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
821 _worst_output_latency > current_block_size)
824 /* we need to capture the audio that has still not yet been received by the system
825 at the time the stop is requested, so we have to roll past that time.
827 we want to declick before stopping, so schedule the autostop for one
828 block before the actual end. we'll declick in the subsequent block,
829 and then we'll really be stopped.
832 Event *ev = new Event (Event::StopOnce, Event::Replace,
833 _transport_frame + _worst_output_latency - current_block_size,
837 transport_sub_state |= StopPendingCapture;
838 pending_abort = abort;
842 if ((transport_sub_state & PendingDeclickOut) == 0) {
843 transport_sub_state |= PendingDeclickOut;
844 /* we'll be called again after the declick */
848 realtime_stop (abort);
849 schedule_butler_transport_work ();
853 Session::start_transport ()
855 _last_roll_location = _transport_frame;
857 /* if record status is Enabled, move it to Recording. if its
858 already Recording, move it to Disabled.
861 switch (record_status()) {
869 disable_record (false);
876 if (!synced_to_jack() || _exporting) {
877 actually_start_transport ();
879 waiting_to_start = true;
884 Session::actually_start_transport ()
886 waiting_to_start = false;
888 transport_sub_state |= PendingDeclickIn;
889 _transport_speed = 1.0;
891 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
892 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
893 (*i)->realtime_set_speed ((*i)->speed(), true);
896 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
898 TransportStateChange (); /* EMIT SIGNAL */
901 /** Do any transport work in the audio thread that needs to be done after the
902 * transport thread is finished. Audio thread, realtime safe.
905 Session::post_transport ()
907 if (post_transport_work & PostTransportAudition) {
908 if (auditioner && auditioner->active()) {
909 process_function = &Session::process_audition;
911 process_function = &Session::process_with_events;
915 if (post_transport_work & PostTransportStop) {
917 transport_sub_state = 0;
920 if (post_transport_work & PostTransportLocate) {
922 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
927 transport_sub_state = 0;
933 post_transport_work = PostTransportWork (0);
937 Session::set_rf_speed (float speed)
940 cumulative_rf_motion = 0;
945 Session::reset_rf_scale (jack_nframes_t motion)
947 cumulative_rf_motion += motion;
949 if (cumulative_rf_motion < 4 * _current_frame_rate) {
951 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
953 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
965 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
967 bool reverse = false;
968 bool non_rt_required = false;
970 if (src == _slave_type) {
974 if (_transport_speed) {
975 error << _("please stop the transport before adjusting slave settings") << endmsg;
976 /* help out non-MVC friendly UI's by telling them the slave type changed */
977 ControlChanged (SlaveType); /* EMIT SIGNAL */
981 // if (src == JACK && Config->get_jack_time_master()) {
991 if (_transport_speed < 0.0) {
1003 _slave = new MTC_Slave (*this, *_mtc_port);
1006 catch (failed_constructor& err) {
1011 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1014 _desired_transport_speed = _transport_speed;
1018 _slave = new JACK_Slave (_engine.jack());
1019 _desired_transport_speed = _transport_speed;
1025 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1026 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1027 if (!(*i)->hidden()) {
1028 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1029 non_rt_required = true;
1031 (*i)->set_slaved (_slave);
1036 reverse_diskstream_buffers ();
1039 if (non_rt_required) {
1040 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1041 schedule_butler_transport_work ();
1045 ControlChanged (SlaveType); /* EMIT SIGNAL */
1051 Session::reverse_diskstream_buffers ()
1053 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1054 schedule_butler_transport_work ();
1058 Session::set_diskstream_speed (Diskstream* stream, float speed)
1060 if (stream->realtime_set_speed (speed, false)) {
1061 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1062 schedule_butler_transport_work ();
1068 Session::set_audio_range (list<AudioRange>& range)
1070 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1071 ev->audio_range = range;
1076 Session::request_play_range (bool yn)
1078 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1083 Session::set_play_range (bool yn)
1085 /* Called from event-processing context */
1087 if (_play_range != yn) {
1092 /* stop transport */
1093 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1097 ControlChanged (PlayRange); /* EMIT SIGNAL */
1102 Session::setup_auto_play ()
1104 /* Called from event-processing context */
1108 _clear_event_type (Event::RangeStop);
1109 _clear_event_type (Event::RangeLocate);
1115 list<AudioRange>::size_type sz = current_audio_range.size();
1119 list<AudioRange>::iterator i = current_audio_range.begin();
1120 list<AudioRange>::iterator next;
1122 while (i != current_audio_range.end()) {
1127 /* locating/stopping is subject to delays for declicking.
1130 jack_nframes_t requested_frame = (*i).end;
1132 if (requested_frame > current_block_size) {
1133 requested_frame -= current_block_size;
1135 requested_frame = 0;
1138 if (next == current_audio_range.end()) {
1139 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1141 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1149 } else if (sz == 1) {
1151 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1156 /* now start rolling at the right place */
1158 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1163 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1166 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1168 request_locate (start, true);
1172 Session::engine_halted ()
1174 /* there will be no more calls to process(), so
1175 we'd better clean up for ourselves, right now.
1177 but first, make sure the butler is out of
1181 g_atomic_int_set (&butler_should_do_transport_work, 0);
1182 post_transport_work = PostTransportWork (0);
1185 realtime_stop (false);
1186 non_realtime_stop (false);
1187 transport_sub_state = 0;
1189 TransportStateChange (); /* EMIT SIGNAL */
1194 Session::xrun_recovery ()
1196 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1198 HaltOnXrun (); /* EMIT SIGNAL */
1200 /* it didn't actually halt, but we need
1201 to handle things in the same way.
1209 Session::update_latency_compensation (bool with_stop, bool abort)
1211 bool update_jack = false;
1213 if (_state_of_the_state & Deletion) {
1217 _worst_track_latency = 0;
1219 boost::shared_ptr<RouteList> r = routes.reader ();
1221 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1223 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1224 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1227 jack_nframes_t old_latency = (*i)->signal_latency ();
1228 jack_nframes_t track_latency = (*i)->update_total_latency ();
1230 if (old_latency != track_latency) {
1234 if (!(*i)->hidden() && ((*i)->active())) {
1235 _worst_track_latency = max (_worst_track_latency, track_latency);
1239 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1240 (*i)->set_latency_delay (_worst_track_latency);
1243 /* tell JACK to play catch up */
1246 _engine.update_total_latencies ();
1249 set_worst_io_latencies ();
1251 /* reflect any changes in latencies into capture offsets
1254 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1256 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1257 (*i)->set_capture_offset ();
1262 Session::update_latency_compensation_proxy (void* ignored)
1264 update_latency_compensation (false, false);