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 // FIXME: where should this really be? [DR]
140 //send_full_time_code();
141 deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
142 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
144 if (_transport_speed < 0.0f) {
145 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
147 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
150 if (actively_recording()) {
152 /* move the transport position back to where the
153 request for a stop was noticed. we rolled
154 past that point to pick up delayed input.
157 #ifndef LEAVE_TRANSPORT_UNADJUSTED
158 decrement_transport_position (_worst_output_latency);
161 /* the duration change is not guaranteed to have happened, but is likely */
163 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
167 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
170 _clear_event_type (Event::StopOnce);
171 _clear_event_type (Event::RangeStop);
172 _clear_event_type (Event::RangeLocate);
174 disable_record (true);
176 reset_slave_state ();
178 _transport_speed = 0;
180 if (Config->get_use_video_sync()) {
181 waiting_for_sync_offset = true;
184 transport_sub_state = (Config->get_auto_return() ? AutoReturning : 0);
188 Session::butler_transport_work ()
192 boost::shared_ptr<RouteList> r = routes.reader ();
193 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
195 int on_entry = g_atomic_int_get (&butler_should_do_transport_work);
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 = dsl->begin(); i != dsl->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 /* don't seek if locate will take care of that in non_realtime_stop() */
223 if (!(post_transport_work & PostTransportLocate)) {
225 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
226 if (!(*i)->hidden()) {
227 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
228 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
231 (*i)->seek (_transport_frame);
234 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
235 /* new request, stop seeking, and start again */
236 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
243 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
244 non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
246 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
251 if (post_transport_work & PostTransportOverWrite) {
252 non_realtime_overwrite (on_entry, finished);
254 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
259 if (post_transport_work & PostTransportAudition) {
260 non_realtime_set_audition ();
263 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
267 Session::non_realtime_set_speed ()
269 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
271 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
272 (*i)->non_realtime_set_speed ();
277 Session::non_realtime_overwrite (int on_entry, bool& finished)
279 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
281 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
282 if ((*i)->pending_overwrite) {
283 (*i)->overwrite_existing_buffers ();
285 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
293 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
303 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
305 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
306 if ((*i)->get_captured_frames () != 0) {
312 /* stop and locate are merged here because they share a lot of common stuff */
315 now = localtime (&xnow);
318 auditioner->cancel_audition ();
322 cumulative_rf_motion = 0;
326 begin_reversible_command ("capture");
328 Location* loc = _locations.end_location();
329 bool change_end = false;
331 if (_transport_frame < loc->end()) {
333 /* stopped recording before current end */
335 if (_end_location_is_free) {
337 /* first capture for this session, move end back to where we are */
342 } else if (_transport_frame > loc->end()) {
344 /* stopped recording after the current end, extend it */
350 XMLNode &before = loc->get_state();
351 loc->set_end(_transport_frame);
352 XMLNode &after = loc->get_state();
353 add_command (new MementoCommand<Location>(*loc, &before, &after));
356 _end_location_is_free = false;
357 _have_captured = true;
360 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
361 (*i)->transport_stopped (*now, xnow, abort);
364 boost::shared_ptr<RouteList> r = routes.reader ();
366 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
367 if (!(*i)->hidden()) {
368 (*i)->set_pending_declick (0);
373 commit_reversible_command ();
376 if (_engine.running()) {
377 update_latency_compensation (true, abort);
380 if (Config->get_auto_return() || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
382 if (pending_locate_flush) {
383 flush_all_redirects ();
386 if ((Config->get_auto_return() || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
388 _transport_frame = last_stop_frame;
390 if (synced_to_jack()) {
391 _engine.transport_locate (_transport_frame);
395 #ifndef LEAVE_TRANSPORT_UNADJUSTED
399 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
400 if (!(*i)->hidden()) {
401 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
402 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
405 (*i)->seek (_transport_frame);
408 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
410 /* we will be back */
415 #ifdef LEAVE_TRANSPORT_UNADJUSTED
419 last_stop_frame = _transport_frame;
423 /* XXX its a little odd that we're doing this here
424 when realtime_stop(), which has already executed,
428 if (!Config->get_latched_record_enable()) {
429 g_atomic_int_set (&_record_status, Disabled);
431 g_atomic_int_set (&_record_status, Enabled);
433 RecordStateChanged (); /* emit signal */
436 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
437 /* capture start has been changed, so save pending state */
438 save_state ("", true);
442 /* always try to get rid of this */
444 remove_pending_capture_state ();
446 /* save the current state of things if appropriate */
448 if (did_record && !saved) {
449 save_state (_current_snapshot_name);
452 if (post_transport_work & PostTransportDuration) {
453 DurationChanged (); /* EMIT SIGNAL */
456 if (post_transport_work & PostTransportStop) {
459 /* do not turn off autoloop on stop */
463 PositionChanged (_transport_frame); /* EMIT SIGNAL */
464 TransportStateChange (); /* EMIT SIGNAL */
466 /* and start it up again if relevant */
468 if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
469 request_transport_speed (1.0);
470 pending_locate_roll = false;
475 Session::check_declick_out ()
477 bool locate_required = transport_sub_state & PendingLocate;
479 /* this is called after a process() iteration. if PendingDeclickOut was set,
480 it means that we were waiting to declick the output (which has just been
481 done) before doing something else. this is where we do that "something else".
483 note: called from the audio thread.
486 if (transport_sub_state & PendingDeclickOut) {
488 if (locate_required) {
489 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
490 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
492 stop_transport (pending_abort);
493 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
499 Session::set_play_loop (bool yn)
501 /* Called from event-handling context */
503 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
509 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
510 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
511 "Recommend changing the configured options")
517 if ((play_loop = yn)) {
522 if ((loc = _locations.auto_loop_location()) != 0) {
524 if (Config->get_seamless_loop()) {
525 // set all diskstreams to use internal looping
526 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
527 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
528 if (!(*i)->hidden()) {
529 (*i)->set_loop (loc);
534 // set all diskstreams to NOT use internal looping
535 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
536 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
537 if (!(*i)->hidden()) {
543 /* stick in the loop event */
545 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
548 /* locate to start of loop and roll if current pos is outside of the loop range */
549 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
550 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
554 // locate to current position (+ 1 to force reload)
555 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
563 clear_events (Event::AutoLoop);
565 // set all diskstreams to NOT use internal looping
566 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
567 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
568 if (!(*i)->hidden()) {
577 Session::flush_all_redirects ()
579 boost::shared_ptr<RouteList> r = routes.reader ();
581 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
582 (*i)->flush_redirects ();
587 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
589 if (synced_to_jack()) {
594 _slave->speed_and_position (sp, pos);
596 if (target_frame != pos) {
598 /* tell JACK to change transport position, and we will
599 follow along later in ::follow_slave()
602 _engine.transport_locate (target_frame);
604 if (sp != 1.0f && with_roll) {
605 _engine.transport_start ();
612 locate (target_frame, with_roll, with_flush, with_loop);
617 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
619 if (actively_recording()) {
623 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
625 set_transport_speed (1.0, false);
627 loop_changing = false;
632 // [DR] FIXME: find out exactly where this should go below
633 _transport_frame = target_frame;
634 smpte_time(_transport_frame, transmitting_smpte_time);
635 outbound_mtc_smpte_frame = _transport_frame;
636 next_quarter_frame_to_send = 0;
638 if (_transport_speed && (!with_loop || loop_changing)) {
639 /* schedule a declick. we'll be called again when its done */
641 if (!(transport_sub_state & PendingDeclickOut)) {
642 transport_sub_state |= (PendingDeclickOut|PendingLocate);
643 pending_locate_frame = target_frame;
644 pending_locate_roll = with_roll;
645 pending_locate_flush = with_flush;
650 if (transport_rolling() && !Config->get_auto_play() && !with_roll && !(synced_to_jack() && play_loop)) {
651 realtime_stop (false);
654 if ( !with_loop || loop_changing) {
656 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
659 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
662 schedule_butler_transport_work ();
666 cerr << "butler not requested\n";
668 /* this is functionally what clear_clicks() does but with a tentative lock */
670 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
672 if (clickm.locked()) {
674 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
683 /* switch from input if we're going to roll */
684 if (Config->get_monitoring_model() == HardwareMonitoring) {
686 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
688 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
689 if ((*i)->record_enabled ()) {
690 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
691 (*i)->monitor_input (!Config->get_auto_input());
696 /* otherwise we're going to stop, so do the opposite */
697 if (Config->get_monitoring_model() == HardwareMonitoring) {
698 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
700 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
701 if ((*i)->record_enabled ()) {
702 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
703 (*i)->monitor_input (true);
709 /* cancel looped playback if transport pos outside of loop range */
711 Location* al = _locations.auto_loop_location();
713 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
714 // cancel looping directly, this is called from event handling context
715 set_play_loop (false);
719 loop_changing = false;
721 _send_smpte_update = true;
725 Session::set_transport_speed (float speed, bool abort)
727 if (_transport_speed == speed) {
732 speed = min (8.0f, speed);
733 } else if (speed < 0) {
734 speed = max (-8.0f, speed);
737 if (transport_rolling() && speed == 0.0) {
739 if (Config->get_monitoring_model() == HardwareMonitoring)
741 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
743 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
744 if ((*i)->record_enabled ()) {
745 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
746 (*i)->monitor_input (true);
751 if (synced_to_jack ()) {
752 _engine.transport_stop ();
754 stop_transport (abort);
757 } else if (transport_stopped() && speed == 1.0) {
759 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
763 if (Config->get_monitoring_model() == HardwareMonitoring) {
765 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
767 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
768 if (Config->get_auto_input() && (*i)->record_enabled ()) {
769 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
770 (*i)->monitor_input (false);
775 if (synced_to_jack()) {
776 _engine.transport_start ();
783 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
787 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
788 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
793 if (actively_recording()) {
797 if (speed > 0.0f && _transport_frame == current_end_frame()) {
801 if (speed < 0.0f && _transport_frame == 0) {
807 /* if we are reversing relative to the current speed, or relative to the speed
808 before the last stop, then we have to do extra work.
811 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
812 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
815 _last_transport_speed = _transport_speed;
816 _transport_speed = speed;
818 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
819 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
820 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
821 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
825 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
826 schedule_butler_transport_work ();
832 Session::stop_transport (bool abort)
834 if (_transport_speed == 0.0f) {
838 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
839 _worst_output_latency > current_block_size)
842 /* we need to capture the audio that has still not yet been received by the system
843 at the time the stop is requested, so we have to roll past that time.
845 we want to declick before stopping, so schedule the autostop for one
846 block before the actual end. we'll declick in the subsequent block,
847 and then we'll really be stopped.
850 Event *ev = new Event (Event::StopOnce, Event::Replace,
851 _transport_frame + _worst_output_latency - current_block_size,
855 transport_sub_state |= StopPendingCapture;
856 pending_abort = abort;
861 if ((transport_sub_state & PendingDeclickOut) == 0) {
862 transport_sub_state |= PendingDeclickOut;
863 /* we'll be called again after the declick */
864 pending_abort = abort;
868 realtime_stop (abort);
869 schedule_butler_transport_work ();
873 Session::start_transport ()
875 _last_roll_location = _transport_frame;
877 /* if record status is Enabled, move it to Recording. if its
878 already Recording, move it to Disabled.
881 switch (record_status()) {
883 if (!Config->get_punch_in()) {
889 disable_record (false);
896 if (!synced_to_jack() || _exporting) {
897 actually_start_transport ();
899 waiting_to_start = true;
904 Session::actually_start_transport ()
906 waiting_to_start = false;
908 transport_sub_state |= PendingDeclickIn;
909 _transport_speed = 1.0;
911 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
912 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
913 (*i)->realtime_set_speed ((*i)->speed(), true);
916 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
918 TransportStateChange (); /* EMIT SIGNAL */
921 /** Do any transport work in the audio thread that needs to be done after the
922 * transport thread is finished. Audio thread, realtime safe.
925 Session::post_transport ()
927 if (post_transport_work & PostTransportAudition) {
928 if (auditioner && auditioner->active()) {
929 process_function = &Session::process_audition;
931 process_function = &Session::process_with_events;
935 if (post_transport_work & PostTransportStop) {
937 transport_sub_state = 0;
940 if (post_transport_work & PostTransportLocate) {
942 if ((Config->get_auto_play() && !_exporting) || (post_transport_work & PostTransportRoll)) {
946 transport_sub_state = 0;
952 post_transport_work = PostTransportWork (0);
956 Session::reset_rf_scale (nframes_t motion)
958 cumulative_rf_motion += motion;
960 if (cumulative_rf_motion < 4 * _current_frame_rate) {
962 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
964 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
976 Session::set_slave_source (SlaveSource src)
978 bool reverse = false;
979 bool non_rt_required = false;
981 if (_transport_speed) {
982 error << _("please stop the transport before adjusting slave settings") << endmsg;
986 // if (src == JACK && Config->get_jack_time_master()) {
995 if (_transport_speed < 0.0) {
1007 _slave = new MTC_Slave (*this, *_mtc_port);
1010 catch (failed_constructor& err) {
1015 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1018 _desired_transport_speed = _transport_speed;
1022 _slave = new JACK_Slave (_engine.jack());
1023 _desired_transport_speed = _transport_speed;
1027 Config->set_slave_source (src);
1029 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1030 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1031 if (!(*i)->hidden()) {
1032 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1033 non_rt_required = true;
1035 (*i)->set_slaved (_slave);
1040 reverse_diskstream_buffers ();
1043 if (non_rt_required) {
1044 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1045 schedule_butler_transport_work ();
1052 Session::reverse_diskstream_buffers ()
1054 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1055 schedule_butler_transport_work ();
1059 Session::set_diskstream_speed (Diskstream* stream, float speed)
1061 if (stream->realtime_set_speed (speed, false)) {
1062 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1063 schedule_butler_transport_work ();
1069 Session::set_audio_range (list<AudioRange>& range)
1071 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1072 ev->audio_range = range;
1077 Session::request_play_range (bool yn)
1079 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1084 Session::set_play_range (bool yn)
1086 /* Called from event-processing context */
1088 if (_play_range != yn) {
1093 /* stop transport */
1094 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1101 Session::setup_auto_play ()
1103 /* Called from event-processing context */
1107 _clear_event_type (Event::RangeStop);
1108 _clear_event_type (Event::RangeLocate);
1114 list<AudioRange>::size_type sz = current_audio_range.size();
1118 list<AudioRange>::iterator i = current_audio_range.begin();
1119 list<AudioRange>::iterator next;
1121 while (i != current_audio_range.end()) {
1126 /* locating/stopping is subject to delays for declicking.
1129 nframes_t requested_frame = (*i).end;
1131 if (requested_frame > current_block_size) {
1132 requested_frame -= current_block_size;
1134 requested_frame = 0;
1137 if (next == current_audio_range.end()) {
1138 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1140 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1148 } else if (sz == 1) {
1150 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1155 /* now start rolling at the right place */
1157 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1162 Session::request_bounded_roll (nframes_t start, nframes_t end)
1165 Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
1167 request_locate (start, true);
1171 Session::engine_halted ()
1175 /* there will be no more calls to process(), so
1176 we'd better clean up for ourselves, right now.
1178 but first, make sure the butler is out of
1182 g_atomic_int_set (&butler_should_do_transport_work, 0);
1183 post_transport_work = PostTransportWork (0);
1186 realtime_stop (false);
1187 non_realtime_stop (false, 0, ignored);
1188 transport_sub_state = 0;
1190 TransportStateChange (); /* EMIT SIGNAL */
1195 Session::xrun_recovery ()
1197 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1199 HaltOnXrun (); /* EMIT SIGNAL */
1201 /* it didn't actually halt, but we need
1202 to handle things in the same way.
1210 Session::update_latency_compensation (bool with_stop, bool abort)
1212 bool update_jack = false;
1214 if (_state_of_the_state & Deletion) {
1218 _worst_track_latency = 0;
1220 boost::shared_ptr<RouteList> r = routes.reader ();
1222 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1224 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1225 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1228 nframes_t old_latency = (*i)->signal_latency ();
1229 nframes_t track_latency = (*i)->update_total_latency ();
1231 if (old_latency != track_latency) {
1235 if (!(*i)->hidden() && ((*i)->active())) {
1236 _worst_track_latency = max (_worst_track_latency, track_latency);
1240 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1241 (*i)->set_latency_delay (_worst_track_latency);
1244 /* tell JACK to play catch up */
1247 _engine.update_total_latencies ();
1250 set_worst_io_latencies ();
1252 /* reflect any changes in latencies into capture offsets
1255 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1257 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1258 (*i)->set_capture_offset ();
1263 Session::update_latency_compensation_proxy (void* ignored)
1265 update_latency_compensation (false, false);