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.
24 #include <sigc++/bind.h>
25 #include <sigc++/retype.h>
28 #include <pbd/error.h>
29 #include <glibmm/thread.h>
30 #include <pbd/pthread_utils.h>
31 #include <pbd/memento_command.h>
33 #include <midi++/mmc.h>
34 #include <midi++/port.h>
36 #include <ardour/ardour.h>
37 #include <ardour/audioengine.h>
38 #include <ardour/session.h>
39 #include <ardour/audio_diskstream.h>
40 #include <ardour/auditioner.h>
41 #include <ardour/slave.h>
42 #include <ardour/location.h>
47 using namespace ARDOUR;
52 Session::request_input_change_handling ()
54 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
55 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
61 Session::request_slave_source (SlaveSource src)
63 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, 0, 0.0);
66 /* could set_seamless_loop() be disposed of entirely?*/
67 Config->set_seamless_loop (false);
69 Config->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 (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 (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_play_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 && Config->get_seamless_loop() && transport_rolling()) {
127 // request an immediate locate to refresh the diskstreams
128 // after disabling looping
129 request_locate (_transport_frame-1, false);
134 Session::realtime_stop (bool abort)
136 /* assume that when we start, we'll be moving forwards */
138 if (_transport_speed < 0.0f) {
139 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
141 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
144 if (actively_recording()) {
146 /* move the transport position back to where the
147 request for a stop was noticed. we rolled
148 past that point to pick up delayed input.
151 #ifndef LEAVE_TRANSPORT_UNADJUSTED
152 decrement_transport_position (_worst_output_latency);
155 /* the duration change is not guaranteed to have happened, but is likely */
157 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
161 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
164 _clear_event_type (Event::StopOnce);
165 _clear_event_type (Event::RangeStop);
166 _clear_event_type (Event::RangeLocate);
168 disable_record (true);
170 reset_slave_state ();
172 _transport_speed = 0;
174 if (Config->get_use_video_sync()) {
175 waiting_for_sync_offset = true;
178 transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0);
182 Session::butler_transport_work ()
186 boost::shared_ptr<RouteList> r = routes.reader ();
187 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
189 int on_entry = g_atomic_int_get (&butler_should_do_transport_work);
192 if (post_transport_work & PostTransportCurveRealloc) {
193 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
194 (*i)->curve_reallocate();
198 if (post_transport_work & PostTransportInputChange) {
199 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
200 (*i)->non_realtime_input_change ();
204 if (post_transport_work & PostTransportSpeed) {
205 non_realtime_set_speed ();
208 if (post_transport_work & PostTransportReverse) {
212 cumulative_rf_motion = 0;
215 /* don't seek if locate will take care of that in non_realtime_stop() */
217 if (!(post_transport_work & PostTransportLocate)) {
219 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
220 if (!(*i)->hidden()) {
221 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
222 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
225 (*i)->seek (_transport_frame);
228 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
229 /* new request, stop seeking, and start again */
230 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
237 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
238 non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
240 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
245 if (post_transport_work & PostTransportOverWrite) {
246 non_realtime_overwrite (on_entry, finished);
248 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
253 if (post_transport_work & PostTransportAudition) {
254 non_realtime_set_audition ();
257 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
261 Session::non_realtime_set_speed ()
263 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
265 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
266 (*i)->non_realtime_set_speed ();
271 Session::non_realtime_overwrite (int on_entry, bool& finished)
273 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
275 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
276 if ((*i)->pending_overwrite) {
277 (*i)->overwrite_existing_buffers ();
279 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
287 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
297 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
299 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
300 if ((*i)->get_captured_frames () != 0) {
306 /* stop and locate are merged here because they share a lot of common stuff */
309 now = localtime (&xnow);
312 auditioner->cancel_audition ();
316 cumulative_rf_motion = 0;
320 begin_reversible_command ("capture");
322 Location* loc = _locations.end_location();
323 bool change_end = false;
325 if (_transport_frame < loc->end()) {
327 /* stopped recording before current end */
329 if (_end_location_is_free) {
331 /* first capture for this session, move end back to where we are */
336 } else if (_transport_frame > loc->end()) {
338 /* stopped recording after the current end, extend it */
344 XMLNode &before = loc->get_state();
345 loc->set_end(_transport_frame);
346 XMLNode &after = loc->get_state();
347 add_command (new MementoCommand<Location>(*loc, &before, &after));
350 _end_location_is_free = false;
351 _have_captured = true;
354 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
355 (*i)->transport_stopped (*now, xnow, abort);
358 boost::shared_ptr<RouteList> r = routes.reader ();
360 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
361 if (!(*i)->hidden()) {
362 (*i)->set_pending_declick (0);
367 commit_reversible_command ();
370 if (_engine.running()) {
371 update_latency_compensation (true, abort);
374 if ((Config->get_slave_source() == None && Config->get_auto_return()) ||
375 (post_transport_work & PostTransportLocate) ||
376 (_requested_return_frame >= 0) ||
379 if (pending_locate_flush) {
380 flush_all_redirects ();
383 if (((Config->get_slave_source() == None && Config->get_auto_return()) ||
385 _requested_return_frame >= 0) &&
386 !(post_transport_work & PostTransportLocate)) {
388 bool do_locate = false;
390 if (_requested_return_frame >= 0) {
391 _transport_frame = _requested_return_frame;
392 _requested_return_frame = -1;
395 _transport_frame = last_stop_frame;
398 if (synced_to_jack() && !play_loop) {
403 // cerr << "non-realtimestop: transport locate to " << _transport_frame << endl;
404 _engine.transport_locate (_transport_frame);
408 #ifndef LEAVE_TRANSPORT_UNADJUSTED
412 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
413 if (!(*i)->hidden()) {
414 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
415 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
418 (*i)->seek (_transport_frame);
421 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
423 /* we will be back */
427 #ifdef LEAVE_TRANSPORT_UNADJUSTED
431 last_stop_frame = _transport_frame;
433 send_full_time_code ();
434 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
435 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
439 /* XXX its a little odd that we're doing this here
440 when realtime_stop(), which has already executed,
442 JLC - so let's not because it seems unnecessary and breaks loop record
445 if (!Config->get_latched_record_enable()) {
446 g_atomic_int_set (&_record_status, Disabled);
448 g_atomic_int_set (&_record_status, Enabled);
450 RecordStateChanged (); /* emit signal */
454 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
455 /* capture start has been changed, so save pending state */
456 save_state ("", true);
460 /* always try to get rid of this */
462 remove_pending_capture_state ();
464 /* save the current state of things if appropriate */
466 if (did_record && !saved) {
467 save_state (_current_snapshot_name);
470 if (post_transport_work & PostTransportDuration) {
471 DurationChanged (); /* EMIT SIGNAL */
474 if (post_transport_work & PostTransportStop) {
477 /* do not turn off autoloop on stop */
481 PositionChanged (_transport_frame); /* EMIT SIGNAL */
482 TransportStateChange (); /* EMIT SIGNAL */
484 /* and start it up again if relevant */
486 if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
487 request_transport_speed (1.0);
488 pending_locate_roll = false;
493 Session::check_declick_out ()
495 bool locate_required = transport_sub_state & PendingLocate;
497 /* this is called after a process() iteration. if PendingDeclickOut was set,
498 it means that we were waiting to declick the output (which has just been
499 done) before doing something else. this is where we do that "something else".
501 note: called from the audio thread.
504 if (transport_sub_state & PendingDeclickOut) {
506 if (locate_required) {
507 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
508 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
510 stop_transport (pending_abort);
511 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
517 Session::set_play_loop (bool yn)
519 /* Called from event-handling context */
521 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
527 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
528 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
529 "Recommend changing the configured options")
535 if ((play_loop = yn)) {
540 if ((loc = _locations.auto_loop_location()) != 0) {
542 if (Config->get_seamless_loop()) {
543 // set all diskstreams to 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()) {
547 (*i)->set_loop (loc);
552 // set all diskstreams to NOT use internal looping
553 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
554 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
555 if (!(*i)->hidden()) {
561 /* stick in the loop event */
563 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
566 /* locate to start of loop and roll if current pos is outside of the loop range */
567 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
568 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
572 // locate to current position (+ 1 to force reload)
573 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
581 clear_events (Event::AutoLoop);
583 // set all diskstreams to NOT use internal looping
584 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
585 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
586 if (!(*i)->hidden()) {
595 Session::flush_all_redirects ()
597 boost::shared_ptr<RouteList> r = routes.reader ();
599 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
600 (*i)->flush_redirects ();
605 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
607 if (synced_to_jack()) {
612 _slave->speed_and_position (sp, pos);
614 if (target_frame != pos) {
616 /* tell JACK to change transport position, and we will
617 follow along later in ::follow_slave()
620 _engine.transport_locate (target_frame);
622 if (sp != 1.0f && with_roll) {
623 _engine.transport_start ();
630 locate (target_frame, with_roll, with_flush, with_loop);
635 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
637 if (actively_recording() && !with_loop) {
641 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
643 set_transport_speed (1.0, false);
645 loop_changing = false;
649 _transport_frame = target_frame;
651 if (_transport_speed && (!with_loop || loop_changing)) {
652 /* schedule a declick. we'll be called again when its done */
654 if (!(transport_sub_state & PendingDeclickOut)) {
655 transport_sub_state |= (PendingDeclickOut|PendingLocate);
656 pending_locate_frame = target_frame;
657 pending_locate_roll = with_roll;
658 pending_locate_flush = with_flush;
663 if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
664 realtime_stop (false);
667 if ( !with_loop || loop_changing) {
669 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
672 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
675 schedule_butler_transport_work ();
679 /* this is functionally what clear_clicks() does but with a tentative lock */
681 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
683 if (clickm.locked()) {
685 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
694 /* switch from input if we're going to roll */
695 if (Config->get_monitoring_model() == HardwareMonitoring) {
697 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
699 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
700 if ((*i)->record_enabled ()) {
701 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
702 (*i)->monitor_input (!Config->get_auto_input());
707 /* otherwise we're going to stop, so do the opposite */
708 if (Config->get_monitoring_model() == HardwareMonitoring) {
709 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
711 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
712 if ((*i)->record_enabled ()) {
713 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
714 (*i)->monitor_input (true);
720 /* cancel looped playback if transport pos outside of loop range */
722 Location* al = _locations.auto_loop_location();
724 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
725 // cancel looping directly, this is called from event handling context
726 set_play_loop (false);
728 else if (al && _transport_frame == al->start()) {
730 // this is only necessary for seamless looping
732 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
734 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
735 if ((*i)->record_enabled ()) {
736 // tell it we've looped, so it can deal with the record state
737 (*i)->transport_looped(_transport_frame);
742 TransportLooped(); // EMIT SIGNAL
746 loop_changing = false;
750 Session::set_transport_speed (float speed, bool abort)
752 if (_transport_speed == speed) {
757 speed = min (8.0f, speed);
758 } else if (speed < 0) {
759 speed = max (-8.0f, speed);
762 if (transport_rolling() && speed == 0.0) {
764 if (Config->get_monitoring_model() == HardwareMonitoring)
766 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
768 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
769 if ((*i)->record_enabled ()) {
770 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
771 (*i)->monitor_input (true);
776 if (synced_to_jack ()) {
777 _engine.transport_stop ();
779 stop_transport (abort);
782 } else if (transport_stopped() && speed == 1.0) {
784 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
788 if (Config->get_monitoring_model() == HardwareMonitoring) {
790 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
792 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
793 if (Config->get_auto_input() && (*i)->record_enabled ()) {
794 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
795 (*i)->monitor_input (false);
800 if (synced_to_jack()) {
801 _engine.transport_start ();
808 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
812 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
813 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
818 if (actively_recording()) {
822 if (speed > 0.0f && _transport_frame == current_end_frame()) {
826 if (speed < 0.0f && _transport_frame == 0) {
832 /* if we are reversing relative to the current speed, or relative to the speed
833 before the last stop, then we have to do extra work.
836 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
837 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
840 _last_transport_speed = _transport_speed;
841 _transport_speed = speed;
843 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
844 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
845 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
846 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
850 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
851 schedule_butler_transport_work ();
857 Session::stop_transport (bool abort)
859 if (_transport_speed == 0.0f) {
863 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
864 _worst_output_latency > current_block_size)
867 /* we need to capture the audio that has still not yet been received by the system
868 at the time the stop is requested, so we have to roll past that time.
870 we want to declick before stopping, so schedule the autostop for one
871 block before the actual end. we'll declick in the subsequent block,
872 and then we'll really be stopped.
875 Event *ev = new Event (Event::StopOnce, Event::Replace,
876 _transport_frame + _worst_output_latency - current_block_size,
880 transport_sub_state |= StopPendingCapture;
881 pending_abort = abort;
886 if ((transport_sub_state & PendingDeclickOut) == 0) {
887 transport_sub_state |= PendingDeclickOut;
888 /* we'll be called again after the declick */
889 pending_abort = abort;
893 realtime_stop (abort);
894 schedule_butler_transport_work ();
898 Session::start_transport ()
900 _last_roll_location = _transport_frame;
902 /* if record status is Enabled, move it to Recording. if its
903 already Recording, move it to Disabled.
906 switch (record_status()) {
908 if (!Config->get_punch_in()) {
915 disable_record (false);
923 if (!synced_to_jack() || _exporting) {
924 actually_start_transport ();
926 waiting_to_start = true;
931 Session::actually_start_transport ()
933 waiting_to_start = false;
935 transport_sub_state |= PendingDeclickIn;
936 _transport_speed = 1.0;
938 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
939 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
940 (*i)->realtime_set_speed ((*i)->speed(), true);
943 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
945 TransportStateChange (); /* EMIT SIGNAL */
949 Session::post_transport ()
951 if (post_transport_work & PostTransportAudition) {
952 if (auditioner && auditioner->active()) {
953 process_function = &Session::process_audition;
955 process_function = &Session::process_with_events;
959 if (post_transport_work & PostTransportStop) {
961 transport_sub_state = 0;
964 if (post_transport_work & PostTransportLocate) {
966 if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
970 transport_sub_state = 0;
976 post_transport_work = PostTransportWork (0);
980 Session::reset_rf_scale (nframes_t motion)
982 cumulative_rf_motion += motion;
984 if (cumulative_rf_motion < 4 * _current_frame_rate) {
986 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
988 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1000 Session::set_slave_source (SlaveSource src)
1002 bool reverse = false;
1003 bool non_rt_required = false;
1005 if (_transport_speed) {
1006 error << _("please stop the transport before adjusting slave settings") << endmsg;
1010 // if (src == JACK && Config->get_jack_time_master()) {
1019 if (_transport_speed < 0.0) {
1031 _slave = new MTC_Slave (*this, *_mtc_port);
1034 catch (failed_constructor& err) {
1039 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1042 _desired_transport_speed = _transport_speed;
1046 _slave = new JACK_Slave (_engine.jack());
1047 _desired_transport_speed = _transport_speed;
1051 Config->set_slave_source (src);
1053 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1054 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1055 if (!(*i)->hidden()) {
1056 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1057 non_rt_required = true;
1059 (*i)->set_slaved (_slave);
1064 reverse_diskstream_buffers ();
1067 if (non_rt_required) {
1068 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1069 schedule_butler_transport_work ();
1076 Session::reverse_diskstream_buffers ()
1078 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1079 schedule_butler_transport_work ();
1083 Session::set_diskstream_speed (Diskstream* stream, float speed)
1085 if (stream->realtime_set_speed (speed, false)) {
1086 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1087 schedule_butler_transport_work ();
1093 Session::set_audio_range (list<AudioRange>& range)
1095 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1096 ev->audio_range = range;
1101 Session::request_play_range (bool yn)
1103 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1108 Session::set_play_range (bool yn)
1110 /* Called from event-processing context */
1112 if (_play_range != yn) {
1117 /* stop transport */
1118 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1125 Session::setup_auto_play ()
1127 /* Called from event-processing context */
1131 _clear_event_type (Event::RangeStop);
1132 _clear_event_type (Event::RangeLocate);
1138 list<AudioRange>::size_type sz = current_audio_range.size();
1142 list<AudioRange>::iterator i = current_audio_range.begin();
1143 list<AudioRange>::iterator next;
1145 while (i != current_audio_range.end()) {
1150 /* locating/stopping is subject to delays for declicking.
1153 nframes_t requested_frame = (*i).end;
1155 if (requested_frame > current_block_size) {
1156 requested_frame -= current_block_size;
1158 requested_frame = 0;
1161 if (next == current_audio_range.end()) {
1162 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1164 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1172 } else if (sz == 1) {
1174 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1179 /* now start rolling at the right place */
1181 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1186 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1188 request_locate (start, false);
1189 Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
1194 Session::request_bounded_roll (nframes_t start, nframes_t end)
1197 Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
1199 request_locate (start, true);
1203 Session::engine_halted ()
1207 /* there will be no more calls to process(), so
1208 we'd better clean up for ourselves, right now.
1210 but first, make sure the butler is out of
1214 g_atomic_int_set (&butler_should_do_transport_work, 0);
1215 post_transport_work = PostTransportWork (0);
1218 realtime_stop (false);
1219 non_realtime_stop (false, 0, ignored);
1220 transport_sub_state = 0;
1222 TransportStateChange (); /* EMIT SIGNAL */
1227 Session::xrun_recovery ()
1229 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1231 HaltOnXrun (); /* EMIT SIGNAL */
1233 /* it didn't actually halt, but we need
1234 to handle things in the same way.
1242 Session::update_latency_compensation (bool with_stop, bool abort)
1244 bool update_jack = false;
1246 if (_state_of_the_state & Deletion) {
1250 _worst_track_latency = 0;
1252 boost::shared_ptr<RouteList> r = routes.reader ();
1254 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1256 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1257 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1260 nframes_t old_latency = (*i)->signal_latency ();
1261 nframes_t track_latency = (*i)->update_total_latency ();
1263 if (old_latency != track_latency) {
1267 if (!(*i)->hidden() && ((*i)->active())) {
1268 _worst_track_latency = max (_worst_track_latency, track_latency);
1272 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1273 (*i)->set_latency_delay (_worst_track_latency);
1276 /* tell JACK to play catch up */
1279 _engine.update_total_latencies ();
1282 set_worst_io_latencies ();
1284 /* reflect any changes in latencies into capture offsets
1287 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1289 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1290 (*i)->set_capture_offset ();
1295 Session::update_latency_compensation_proxy (void* ignored)
1297 update_latency_compensation (false, false);
1301 Session::allow_auto_play (bool yn)
1303 auto_play_legal = yn;
1307 Session::reset_jack_connection (jack_client_t* jack)
1311 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1312 js->reset_client (jack);