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 nframes_t tf = _transport_frame;
483 PositionChanged (tf); /* EMIT SIGNAL */
484 TransportStateChange (); /* EMIT SIGNAL */
486 /* and start it up again if relevant */
488 if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
489 request_transport_speed (1.0);
490 pending_locate_roll = false;
495 Session::check_declick_out ()
497 bool locate_required = transport_sub_state & PendingLocate;
499 /* this is called after a process() iteration. if PendingDeclickOut was set,
500 it means that we were waiting to declick the output (which has just been
501 done) before doing something else. this is where we do that "something else".
503 note: called from the audio thread.
506 if (transport_sub_state & PendingDeclickOut) {
508 if (locate_required) {
509 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
510 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
512 stop_transport (pending_abort);
513 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
519 Session::set_play_loop (bool yn)
521 /* Called from event-handling context */
523 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
529 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
530 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
531 "Recommend changing the configured options")
537 if ((play_loop = yn)) {
542 if ((loc = _locations.auto_loop_location()) != 0) {
544 if (Config->get_seamless_loop()) {
545 // set all diskstreams to use internal looping
546 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
547 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
548 if (!(*i)->hidden()) {
549 (*i)->set_loop (loc);
554 // set all diskstreams to NOT use internal looping
555 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
556 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
557 if (!(*i)->hidden()) {
563 /* stick in the loop event */
565 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
568 /* locate to start of loop and roll if current pos is outside of the loop range */
569 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
570 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
574 // locate to current position (+ 1 to force reload)
575 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
583 clear_events (Event::AutoLoop);
585 // set all diskstreams to NOT use internal looping
586 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
587 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
588 if (!(*i)->hidden()) {
597 Session::flush_all_redirects ()
599 boost::shared_ptr<RouteList> r = routes.reader ();
601 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
602 (*i)->flush_redirects ();
607 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
609 if (synced_to_jack()) {
614 _slave->speed_and_position (sp, pos);
616 if (target_frame != pos) {
618 /* tell JACK to change transport position, and we will
619 follow along later in ::follow_slave()
622 _engine.transport_locate (target_frame);
624 if (sp != 1.0f && with_roll) {
625 _engine.transport_start ();
632 locate (target_frame, with_roll, with_flush, with_loop);
637 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
639 if (actively_recording() && !with_loop) {
643 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
645 set_transport_speed (1.0, false);
647 loop_changing = false;
651 _transport_frame = target_frame;
653 if (_transport_speed && (!with_loop || loop_changing)) {
654 /* schedule a declick. we'll be called again when its done */
656 if (!(transport_sub_state & PendingDeclickOut)) {
657 transport_sub_state |= (PendingDeclickOut|PendingLocate);
658 pending_locate_frame = target_frame;
659 pending_locate_roll = with_roll;
660 pending_locate_flush = with_flush;
665 if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
666 realtime_stop (false);
669 if ( !with_loop || loop_changing) {
671 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
674 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
677 schedule_butler_transport_work ();
681 /* this is functionally what clear_clicks() does but with a tentative lock */
683 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
685 if (clickm.locked()) {
687 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
696 /* switch from input if we're going to roll */
697 if (Config->get_monitoring_model() == HardwareMonitoring) {
699 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
701 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
702 if ((*i)->record_enabled ()) {
703 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
704 (*i)->monitor_input (!Config->get_auto_input());
709 /* otherwise we're going to stop, so do the opposite */
710 if (Config->get_monitoring_model() == HardwareMonitoring) {
711 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
713 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
714 if ((*i)->record_enabled ()) {
715 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
716 (*i)->monitor_input (true);
722 /* cancel looped playback if transport pos outside of loop range */
724 Location* al = _locations.auto_loop_location();
726 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
727 // cancel looping directly, this is called from event handling context
728 set_play_loop (false);
730 else if (al && _transport_frame == al->start()) {
732 // this is only necessary for seamless looping
734 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
736 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
737 if ((*i)->record_enabled ()) {
738 // tell it we've looped, so it can deal with the record state
739 (*i)->transport_looped(_transport_frame);
744 TransportLooped(); // EMIT SIGNAL
748 loop_changing = false;
752 Session::set_transport_speed (float speed, bool abort)
754 if (_transport_speed == speed) {
759 speed = min (8.0f, speed);
760 } else if (speed < 0) {
761 speed = max (-8.0f, speed);
764 if (transport_rolling() && speed == 0.0) {
766 if (Config->get_monitoring_model() == HardwareMonitoring)
768 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
770 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
771 if ((*i)->record_enabled ()) {
772 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
773 (*i)->monitor_input (true);
778 if (synced_to_jack ()) {
779 _engine.transport_stop ();
781 stop_transport (abort);
784 } else if (transport_stopped() && speed == 1.0) {
786 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
790 if (Config->get_monitoring_model() == HardwareMonitoring) {
792 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
794 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
795 if (Config->get_auto_input() && (*i)->record_enabled ()) {
796 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
797 (*i)->monitor_input (false);
802 if (synced_to_jack()) {
803 _engine.transport_start ();
810 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
814 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
815 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
820 if (actively_recording()) {
824 if (speed > 0.0f && _transport_frame == current_end_frame()) {
828 if (speed < 0.0f && _transport_frame == 0) {
834 /* if we are reversing relative to the current speed, or relative to the speed
835 before the last stop, then we have to do extra work.
838 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
839 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
842 _last_transport_speed = _transport_speed;
843 _transport_speed = speed;
845 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
846 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
847 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
848 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
852 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
853 schedule_butler_transport_work ();
859 Session::stop_transport (bool abort)
861 if (_transport_speed == 0.0f) {
865 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
866 _worst_output_latency > current_block_size)
869 /* we need to capture the audio that has still not yet been received by the system
870 at the time the stop is requested, so we have to roll past that time.
872 we want to declick before stopping, so schedule the autostop for one
873 block before the actual end. we'll declick in the subsequent block,
874 and then we'll really be stopped.
877 Event *ev = new Event (Event::StopOnce, Event::Replace,
878 _transport_frame + _worst_output_latency - current_block_size,
882 transport_sub_state |= StopPendingCapture;
883 pending_abort = abort;
888 if ((transport_sub_state & PendingDeclickOut) == 0) {
889 transport_sub_state |= PendingDeclickOut;
890 /* we'll be called again after the declick */
891 pending_abort = abort;
895 realtime_stop (abort);
896 schedule_butler_transport_work ();
900 Session::start_transport ()
902 _last_roll_location = _transport_frame;
904 /* if record status is Enabled, move it to Recording. if its
905 already Recording, move it to Disabled.
908 switch (record_status()) {
910 if (!Config->get_punch_in()) {
917 disable_record (false);
925 if (!synced_to_jack() || _exporting) {
926 actually_start_transport ();
928 waiting_to_start = true;
933 Session::actually_start_transport ()
935 waiting_to_start = false;
937 transport_sub_state |= PendingDeclickIn;
938 _transport_speed = 1.0;
940 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
941 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
942 (*i)->realtime_set_speed ((*i)->speed(), true);
945 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
947 TransportStateChange (); /* EMIT SIGNAL */
951 Session::post_transport ()
953 if (post_transport_work & PostTransportAudition) {
954 if (auditioner && auditioner->active()) {
955 process_function = &Session::process_audition;
957 process_function = &Session::process_with_events;
961 if (post_transport_work & PostTransportStop) {
963 transport_sub_state = 0;
966 if (post_transport_work & PostTransportLocate) {
968 if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
972 transport_sub_state = 0;
978 post_transport_work = PostTransportWork (0);
982 Session::reset_rf_scale (nframes_t motion)
984 cumulative_rf_motion += motion;
986 if (cumulative_rf_motion < 4 * _current_frame_rate) {
988 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
990 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1002 Session::set_slave_source (SlaveSource src)
1004 bool reverse = false;
1005 bool non_rt_required = false;
1007 if (_transport_speed) {
1008 error << _("please stop the transport before adjusting slave settings") << endmsg;
1012 // if (src == JACK && Config->get_jack_time_master()) {
1021 if (_transport_speed < 0.0) {
1033 _slave = new MTC_Slave (*this, *_mtc_port);
1036 catch (failed_constructor& err) {
1041 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1044 _desired_transport_speed = _transport_speed;
1048 _slave = new JACK_Slave (_engine.jack());
1049 _desired_transport_speed = _transport_speed;
1053 Config->set_slave_source (src);
1055 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1056 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1057 if (!(*i)->hidden()) {
1058 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1059 non_rt_required = true;
1061 (*i)->set_slaved (_slave);
1066 reverse_diskstream_buffers ();
1069 if (non_rt_required) {
1070 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1071 schedule_butler_transport_work ();
1078 Session::reverse_diskstream_buffers ()
1080 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1081 schedule_butler_transport_work ();
1085 Session::set_diskstream_speed (Diskstream* stream, float speed)
1087 if (stream->realtime_set_speed (speed, false)) {
1088 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1089 schedule_butler_transport_work ();
1095 Session::set_audio_range (list<AudioRange>& range)
1097 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1098 ev->audio_range = range;
1103 Session::request_play_range (bool yn)
1105 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1110 Session::set_play_range (bool yn)
1112 /* Called from event-processing context */
1114 if (_play_range != yn) {
1119 /* stop transport */
1120 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1127 Session::setup_auto_play ()
1129 /* Called from event-processing context */
1133 _clear_event_type (Event::RangeStop);
1134 _clear_event_type (Event::RangeLocate);
1140 list<AudioRange>::size_type sz = current_audio_range.size();
1144 list<AudioRange>::iterator i = current_audio_range.begin();
1145 list<AudioRange>::iterator next;
1147 while (i != current_audio_range.end()) {
1152 /* locating/stopping is subject to delays for declicking.
1155 nframes_t requested_frame = (*i).end;
1157 if (requested_frame > current_block_size) {
1158 requested_frame -= current_block_size;
1160 requested_frame = 0;
1163 if (next == current_audio_range.end()) {
1164 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1166 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1174 } else if (sz == 1) {
1176 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1181 /* now start rolling at the right place */
1183 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1188 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1190 request_locate (start, false);
1191 Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
1196 Session::request_bounded_roll (nframes_t start, nframes_t end)
1199 Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
1201 request_locate (start, true);
1205 Session::engine_halted ()
1209 /* there will be no more calls to process(), so
1210 we'd better clean up for ourselves, right now.
1212 but first, make sure the butler is out of
1216 g_atomic_int_set (&butler_should_do_transport_work, 0);
1217 post_transport_work = PostTransportWork (0);
1220 realtime_stop (false);
1221 non_realtime_stop (false, 0, ignored);
1222 transport_sub_state = 0;
1224 TransportStateChange (); /* EMIT SIGNAL */
1229 Session::xrun_recovery ()
1231 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1233 HaltOnXrun (); /* EMIT SIGNAL */
1235 /* it didn't actually halt, but we need
1236 to handle things in the same way.
1244 Session::update_latency_compensation (bool with_stop, bool abort)
1246 bool update_jack = false;
1248 if (_state_of_the_state & Deletion) {
1252 _worst_track_latency = 0;
1254 boost::shared_ptr<RouteList> r = routes.reader ();
1256 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1258 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1259 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1262 nframes_t old_latency = (*i)->signal_latency ();
1263 nframes_t track_latency = (*i)->update_total_latency ();
1265 if (old_latency != track_latency) {
1269 if (!(*i)->hidden() && ((*i)->active())) {
1270 _worst_track_latency = max (_worst_track_latency, track_latency);
1274 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1275 (*i)->set_latency_delay (_worst_track_latency);
1278 /* tell JACK to play catch up */
1281 _engine.update_total_latencies ();
1284 set_worst_io_latencies ();
1286 /* reflect any changes in latencies into capture offsets
1289 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1291 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1292 (*i)->set_capture_offset ();
1297 Session::update_latency_compensation_proxy (void* ignored)
1299 update_latency_compensation (false, false);
1303 Session::allow_auto_play (bool yn)
1305 auto_play_legal = yn;
1309 Session::reset_jack_connection (jack_client_t* jack)
1313 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1314 js->reset_client (jack);