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>
32 #include <pbd/stacktrace.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 if (_transport_speed < 0.0f) {
140 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
142 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
145 if (actively_recording()) {
147 /* move the transport position back to where the
148 request for a stop was noticed. we rolled
149 past that point to pick up delayed input.
152 #ifndef LEAVE_TRANSPORT_UNADJUSTED
153 decrement_transport_position (_worst_output_latency);
156 /* the duration change is not guaranteed to have happened, but is likely */
158 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
162 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
165 _clear_event_type (Event::StopOnce);
166 _clear_event_type (Event::RangeStop);
167 _clear_event_type (Event::RangeLocate);
169 disable_record (true);
171 reset_slave_state ();
173 _transport_speed = 0;
175 if (Config->get_use_video_sync()) {
176 waiting_for_sync_offset = true;
179 transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0);
183 Session::butler_transport_work ()
187 boost::shared_ptr<RouteList> r = routes.reader ();
188 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
190 int on_entry = g_atomic_int_get (&butler_should_do_transport_work);
193 if (post_transport_work & PostTransportCurveRealloc) {
194 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
195 (*i)->curve_reallocate();
199 if (post_transport_work & PostTransportInputChange) {
200 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
201 (*i)->non_realtime_input_change ();
205 if (post_transport_work & PostTransportSpeed) {
206 non_realtime_set_speed ();
209 if (post_transport_work & PostTransportReverse) {
213 cumulative_rf_motion = 0;
216 /* don't seek if locate will take care of that in non_realtime_stop() */
218 if (!(post_transport_work & PostTransportLocate)) {
220 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
221 if (!(*i)->hidden()) {
222 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
223 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
226 (*i)->seek (_transport_frame);
229 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
230 /* new request, stop seeking, and start again */
231 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
238 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
239 non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
241 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
246 if (post_transport_work & PostTransportOverWrite) {
247 non_realtime_overwrite (on_entry, finished);
249 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
254 if (post_transport_work & PostTransportAudition) {
255 non_realtime_set_audition ();
258 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
262 Session::non_realtime_set_speed ()
264 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
266 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
267 (*i)->non_realtime_set_speed ();
272 Session::non_realtime_overwrite (int on_entry, bool& finished)
274 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
276 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
277 if ((*i)->pending_overwrite) {
278 (*i)->overwrite_existing_buffers ();
280 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
288 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
298 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
300 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
301 if ((*i)->get_captured_frames () != 0) {
307 /* stop and locate are merged here because they share a lot of common stuff */
310 now = localtime (&xnow);
313 auditioner->cancel_audition ();
317 cumulative_rf_motion = 0;
321 begin_reversible_command ("capture");
323 Location* loc = _locations.end_location();
324 bool change_end = false;
326 if (_transport_frame < loc->end()) {
328 /* stopped recording before current end */
330 if (_end_location_is_free) {
332 /* first capture for this session, move end back to where we are */
337 } else if (_transport_frame > loc->end()) {
339 /* stopped recording after the current end, extend it */
345 XMLNode &before = loc->get_state();
346 loc->set_end(_transport_frame);
347 XMLNode &after = loc->get_state();
348 add_command (new MementoCommand<Location>(*loc, &before, &after));
351 _end_location_is_free = false;
352 _have_captured = true;
355 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
356 (*i)->transport_stopped (*now, xnow, abort);
359 boost::shared_ptr<RouteList> r = routes.reader ();
361 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
362 if (!(*i)->hidden()) {
363 (*i)->set_pending_declick (0);
368 commit_reversible_command ();
371 if (_engine.running()) {
372 update_latency_compensation (true, abort);
375 if ((Config->get_slave_source() == None && Config->get_auto_return()) ||
376 (post_transport_work & PostTransportLocate) ||
377 (_requested_return_frame >= 0) ||
380 if (pending_locate_flush) {
381 flush_all_redirects ();
384 if (((Config->get_slave_source() == None && Config->get_auto_return()) ||
386 _requested_return_frame >= 0) &&
387 !(post_transport_work & PostTransportLocate)) {
389 bool do_locate = false;
391 if (_requested_return_frame >= 0) {
392 _transport_frame = _requested_return_frame;
393 _requested_return_frame = -1;
396 _transport_frame = last_stop_frame;
399 if (synced_to_jack() && !play_loop) {
404 // cerr << "non-realtimestop: transport locate to " << _transport_frame << endl;
405 _engine.transport_locate (_transport_frame);
409 #ifndef LEAVE_TRANSPORT_UNADJUSTED
413 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
414 if (!(*i)->hidden()) {
415 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
416 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
419 (*i)->seek (_transport_frame);
422 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
424 /* we will be back */
428 #ifdef LEAVE_TRANSPORT_UNADJUSTED
432 last_stop_frame = _transport_frame;
434 send_full_time_code ();
435 deliver_mmc (MIDI::MachineControl::cmdStop, 0);
436 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
440 /* XXX its a little odd that we're doing this here
441 when realtime_stop(), which has already executed,
443 JLC - so let's not because it seems unnecessary and breaks loop record
446 if (!Config->get_latched_record_enable()) {
447 g_atomic_int_set (&_record_status, Disabled);
449 g_atomic_int_set (&_record_status, Enabled);
451 RecordStateChanged (); /* emit signal */
455 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
456 /* capture start has been changed, so save pending state */
457 save_state ("", true);
461 /* always try to get rid of this */
463 remove_pending_capture_state ();
465 /* save the current state of things if appropriate */
467 if (did_record && !saved) {
468 save_state (_current_snapshot_name);
471 if (post_transport_work & PostTransportDuration) {
472 DurationChanged (); /* EMIT SIGNAL */
475 if (post_transport_work & PostTransportStop) {
478 /* do not turn off autoloop on stop */
482 nframes_t tf = _transport_frame;
484 PositionChanged (tf); /* EMIT SIGNAL */
485 TransportStateChange (); /* EMIT SIGNAL */
487 /* and start it up again if relevant */
489 if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
490 request_transport_speed (1.0);
491 pending_locate_roll = false;
496 Session::check_declick_out ()
498 bool locate_required = transport_sub_state & PendingLocate;
500 /* this is called after a process() iteration. if PendingDeclickOut was set,
501 it means that we were waiting to declick the output (which has just been
502 done) before doing something else. this is where we do that "something else".
504 note: called from the audio thread.
507 if (transport_sub_state & PendingDeclickOut) {
509 if (locate_required) {
510 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
511 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
513 stop_transport (pending_abort);
514 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
520 Session::set_play_loop (bool yn)
522 /* Called from event-handling context */
524 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
530 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
531 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
532 "Recommend changing the configured options")
538 if ((play_loop = yn)) {
543 if ((loc = _locations.auto_loop_location()) != 0) {
545 if (Config->get_seamless_loop()) {
546 // set all diskstreams to use internal looping
547 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
548 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
549 if (!(*i)->hidden()) {
550 (*i)->set_loop (loc);
555 // set all diskstreams to NOT use internal looping
556 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
557 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
558 if (!(*i)->hidden()) {
564 /* stick in the loop event */
566 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
569 /* locate to start of loop and roll if current pos is outside of the loop range */
570 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
571 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
575 // locate to current position (+ 1 to force reload)
576 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
584 clear_events (Event::AutoLoop);
586 // set all diskstreams to NOT use internal looping
587 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
588 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
589 if (!(*i)->hidden()) {
598 Session::flush_all_redirects ()
600 boost::shared_ptr<RouteList> r = routes.reader ();
602 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
603 (*i)->flush_redirects ();
608 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
610 if (synced_to_jack()) {
615 _slave->speed_and_position (sp, pos);
617 if (target_frame != pos) {
619 /* tell JACK to change transport position, and we will
620 follow along later in ::follow_slave()
623 _engine.transport_locate (target_frame);
625 if (sp != 1.0f && with_roll) {
626 _engine.transport_start ();
633 locate (target_frame, with_roll, with_flush, with_loop);
638 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
640 if (actively_recording() && !with_loop) {
644 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
646 set_transport_speed (1.0, false);
648 loop_changing = false;
652 _transport_frame = target_frame;
654 if (_transport_speed && (!with_loop || loop_changing)) {
655 /* schedule a declick. we'll be called again when its done */
657 if (!(transport_sub_state & PendingDeclickOut)) {
658 transport_sub_state |= (PendingDeclickOut|PendingLocate);
659 pending_locate_frame = target_frame;
660 pending_locate_roll = with_roll;
661 pending_locate_flush = with_flush;
666 if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
667 realtime_stop (false);
670 if ( !with_loop || loop_changing) {
672 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
675 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
678 schedule_butler_transport_work ();
682 /* this is functionally what clear_clicks() does but with a tentative lock */
684 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
686 if (clickm.locked()) {
688 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
697 /* switch from input if we're going to roll */
698 if (Config->get_monitoring_model() == HardwareMonitoring) {
700 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
702 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
703 if ((*i)->record_enabled ()) {
704 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
705 (*i)->monitor_input (!Config->get_auto_input());
710 /* otherwise we're going to stop, so do the opposite */
711 if (Config->get_monitoring_model() == HardwareMonitoring) {
712 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
714 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
715 if ((*i)->record_enabled ()) {
716 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
717 (*i)->monitor_input (true);
723 /* cancel looped playback if transport pos outside of loop range */
725 Location* al = _locations.auto_loop_location();
727 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
728 // cancel looping directly, this is called from event handling context
729 set_play_loop (false);
731 else if (al && _transport_frame == al->start()) {
733 // this is only necessary for seamless looping
735 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
737 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
738 if ((*i)->record_enabled ()) {
739 // tell it we've looped, so it can deal with the record state
740 (*i)->transport_looped(_transport_frame);
745 TransportLooped(); // EMIT SIGNAL
749 loop_changing = false;
753 Session::set_transport_speed (float speed, bool abort)
755 if (_transport_speed == speed) {
760 speed = min (8.0f, speed);
761 } else if (speed < 0) {
762 speed = max (-8.0f, speed);
765 if (transport_rolling() && speed == 0.0) {
767 if (Config->get_monitoring_model() == HardwareMonitoring)
769 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
771 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
772 if ((*i)->record_enabled ()) {
773 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
774 (*i)->monitor_input (true);
779 if (synced_to_jack ()) {
780 _engine.transport_stop ();
782 stop_transport (abort);
785 } else if (transport_stopped() && speed == 1.0) {
787 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
791 if (Config->get_monitoring_model() == HardwareMonitoring) {
793 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
795 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
796 if (Config->get_auto_input() && (*i)->record_enabled ()) {
797 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
798 (*i)->monitor_input (false);
803 if (synced_to_jack()) {
804 _engine.transport_start ();
811 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
815 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
816 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
821 if (actively_recording()) {
825 if (speed > 0.0f && _transport_frame == current_end_frame()) {
829 if (speed < 0.0f && _transport_frame == 0) {
835 /* if we are reversing relative to the current speed, or relative to the speed
836 before the last stop, then we have to do extra work.
839 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
840 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
843 _last_transport_speed = _transport_speed;
844 _transport_speed = speed;
846 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
847 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
848 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
849 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
853 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
854 schedule_butler_transport_work ();
860 Session::stop_transport (bool abort)
862 if (_transport_speed == 0.0f) {
866 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
867 _worst_output_latency > current_block_size)
870 /* we need to capture the audio that has still not yet been received by the system
871 at the time the stop is requested, so we have to roll past that time.
873 we want to declick before stopping, so schedule the autostop for one
874 block before the actual end. we'll declick in the subsequent block,
875 and then we'll really be stopped.
878 Event *ev = new Event (Event::StopOnce, Event::Replace,
879 _transport_frame + _worst_output_latency - current_block_size,
883 transport_sub_state |= StopPendingCapture;
884 pending_abort = abort;
889 if ((transport_sub_state & PendingDeclickOut) == 0) {
890 transport_sub_state |= PendingDeclickOut;
891 /* we'll be called again after the declick */
892 pending_abort = abort;
896 realtime_stop (abort);
897 schedule_butler_transport_work ();
901 Session::start_transport ()
903 _last_roll_location = _transport_frame;
905 /* if record status is Enabled, move it to Recording. if its
906 already Recording, move it to Disabled.
909 switch (record_status()) {
911 if (!Config->get_punch_in()) {
918 disable_record (false);
926 if (!synced_to_jack() || _exporting) {
927 actually_start_transport ();
929 waiting_to_start = true;
934 Session::actually_start_transport ()
936 waiting_to_start = false;
938 transport_sub_state |= PendingDeclickIn;
939 _transport_speed = 1.0;
941 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
942 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
943 (*i)->realtime_set_speed ((*i)->speed(), true);
946 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
948 TransportStateChange (); /* EMIT SIGNAL */
952 Session::post_transport ()
954 if (post_transport_work & PostTransportAudition) {
955 if (auditioner && auditioner->active()) {
956 process_function = &Session::process_audition;
958 process_function = &Session::process_with_events;
962 if (post_transport_work & PostTransportStop) {
964 transport_sub_state = 0;
967 if (post_transport_work & PostTransportLocate) {
969 if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
973 transport_sub_state = 0;
979 post_transport_work = PostTransportWork (0);
983 Session::reset_rf_scale (nframes_t motion)
985 cumulative_rf_motion += motion;
987 if (cumulative_rf_motion < 4 * _current_frame_rate) {
989 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
991 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1003 Session::set_slave_source (SlaveSource src)
1005 bool reverse = false;
1006 bool non_rt_required = false;
1008 if (_transport_speed) {
1009 error << _("please stop the transport before adjusting slave settings") << endmsg;
1013 // if (src == JACK && Config->get_jack_time_master()) {
1022 if (_transport_speed < 0.0) {
1034 _slave = new MTC_Slave (*this, *_mtc_port);
1037 catch (failed_constructor& err) {
1042 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1045 _desired_transport_speed = _transport_speed;
1049 _slave = new JACK_Slave (_engine.jack());
1050 _desired_transport_speed = _transport_speed;
1054 Config->set_slave_source (src);
1056 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1057 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1058 if (!(*i)->hidden()) {
1059 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1060 non_rt_required = true;
1062 (*i)->set_slaved (_slave);
1067 reverse_diskstream_buffers ();
1070 if (non_rt_required) {
1071 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1072 schedule_butler_transport_work ();
1079 Session::reverse_diskstream_buffers ()
1081 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1082 schedule_butler_transport_work ();
1086 Session::set_diskstream_speed (Diskstream* stream, float speed)
1088 if (stream->realtime_set_speed (speed, false)) {
1089 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1090 schedule_butler_transport_work ();
1096 Session::set_audio_range (list<AudioRange>& range)
1098 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1099 ev->audio_range = range;
1104 Session::request_play_range (bool yn)
1106 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1111 Session::set_play_range (bool yn)
1113 /* Called from event-processing context */
1115 if (_play_range != yn) {
1120 /* stop transport */
1121 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1128 Session::setup_auto_play ()
1130 /* Called from event-processing context */
1134 _clear_event_type (Event::RangeStop);
1135 _clear_event_type (Event::RangeLocate);
1141 list<AudioRange>::size_type sz = current_audio_range.size();
1145 list<AudioRange>::iterator i = current_audio_range.begin();
1146 list<AudioRange>::iterator next;
1148 while (i != current_audio_range.end()) {
1153 /* locating/stopping is subject to delays for declicking.
1156 nframes_t requested_frame = (*i).end;
1158 if (requested_frame > current_block_size) {
1159 requested_frame -= current_block_size;
1161 requested_frame = 0;
1164 if (next == current_audio_range.end()) {
1165 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1167 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1175 } else if (sz == 1) {
1177 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1182 /* now start rolling at the right place */
1184 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1189 Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
1191 request_locate (start, false);
1192 Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
1197 Session::request_bounded_roll (nframes_t start, nframes_t end)
1200 Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
1202 request_locate (start, true);
1206 Session::engine_halted ()
1210 /* there will be no more calls to process(), so
1211 we'd better clean up for ourselves, right now.
1213 but first, make sure the butler is out of
1217 g_atomic_int_set (&butler_should_do_transport_work, 0);
1218 post_transport_work = PostTransportWork (0);
1221 realtime_stop (false);
1222 non_realtime_stop (false, 0, ignored);
1223 transport_sub_state = 0;
1225 TransportStateChange (); /* EMIT SIGNAL */
1230 Session::xrun_recovery ()
1232 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1234 HaltOnXrun (); /* EMIT SIGNAL */
1236 /* it didn't actually halt, but we need
1237 to handle things in the same way.
1245 Session::update_latency_compensation (bool with_stop, bool abort)
1247 bool update_jack = false;
1249 if (_state_of_the_state & Deletion) {
1253 _worst_track_latency = 0;
1255 boost::shared_ptr<RouteList> r = routes.reader ();
1257 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1259 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1260 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1263 nframes_t old_latency = (*i)->signal_latency ();
1264 nframes_t track_latency = (*i)->update_total_latency ();
1266 if (old_latency != track_latency) {
1270 if (!(*i)->hidden() && ((*i)->active())) {
1271 _worst_track_latency = max (_worst_track_latency, track_latency);
1275 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1276 (*i)->set_latency_delay (_worst_track_latency);
1279 /* tell JACK to play catch up */
1282 _engine.update_total_latencies ();
1285 set_worst_io_latencies ();
1287 /* reflect any changes in latencies into capture offsets
1290 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1292 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1293 (*i)->set_capture_offset ();
1298 Session::update_latency_compensation_proxy (void* ignored)
1300 update_latency_compensation (false, false);
1304 Session::allow_auto_play (bool yn)
1306 auto_play_legal = yn;
1310 Session::reset_jack_connection (jack_client_t* jack)
1314 if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1315 js->reset_client (jack);