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 (boost::shared_ptr<Diskstream> ds)
54 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
55 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) {
201 RCUWriter<DiskstreamList> input_writer (diskstreams_input_pending);
202 boost::shared_ptr<DiskstreamList> input_list = input_writer.get_copy ();
203 RCUWriter<DiskstreamList> dswriter (diskstreams);
204 boost::shared_ptr<DiskstreamList> ds = dswriter.get_copy();
206 for (DiskstreamList::iterator i = input_list->begin(); i != input_list->end(); ++i) {
208 /* make the change */
210 (*i)->non_realtime_input_change ();
212 /* now transfer it back onto the regular diskstreams list */
220 diskstreams_input_pending.flush ();
223 if (post_transport_work & PostTransportSpeed) {
224 non_realtime_set_speed ();
227 if (post_transport_work & PostTransportReverse) {
231 cumulative_rf_motion = 0;
234 /* don't seek if locate will take care of that in non_realtime_stop() */
236 if (!(post_transport_work & PostTransportLocate)) {
238 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
239 if (!(*i)->hidden()) {
240 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
241 (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
244 (*i)->seek (_transport_frame);
247 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
248 /* new request, stop seeking, and start again */
249 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
256 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
257 non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
259 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
264 if (post_transport_work & PostTransportOverWrite) {
265 non_realtime_overwrite (on_entry, finished);
267 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
272 if (post_transport_work & PostTransportAudition) {
273 non_realtime_set_audition ();
276 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
280 Session::non_realtime_set_speed ()
282 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
284 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
285 (*i)->non_realtime_set_speed ();
290 Session::non_realtime_overwrite (int on_entry, bool& finished)
292 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
294 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
295 if ((*i)->pending_overwrite) {
296 (*i)->overwrite_existing_buffers ();
298 if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
306 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
316 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
318 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
319 if ((*i)->get_captured_frames () != 0) {
325 /* stop and locate are merged here because they share a lot of common stuff */
328 now = localtime (&xnow);
331 auditioner->cancel_audition ();
335 cumulative_rf_motion = 0;
339 begin_reversible_command ("capture");
341 Location* loc = _locations.end_location();
342 bool change_end = false;
344 if (_transport_frame < loc->end()) {
346 /* stopped recording before current end */
348 if (_end_location_is_free) {
350 /* first capture for this session, move end back to where we are */
355 } else if (_transport_frame > loc->end()) {
357 /* stopped recording after the current end, extend it */
363 XMLNode &before = loc->get_state();
364 loc->set_end(_transport_frame);
365 XMLNode &after = loc->get_state();
366 add_command (new MementoCommand<Location>(*loc, &before, &after));
369 _end_location_is_free = false;
370 _have_captured = true;
373 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
374 (*i)->transport_stopped (*now, xnow, abort);
377 boost::shared_ptr<RouteList> r = routes.reader ();
379 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
380 if (!(*i)->hidden()) {
381 (*i)->set_pending_declick (0);
386 commit_reversible_command ();
389 if (_engine.running()) {
390 update_latency_compensation (true, abort);
393 if ((Config->get_slave_source() == None && Config->get_auto_return()) || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
395 if (pending_locate_flush) {
396 flush_all_redirects ();
399 if (((Config->get_slave_source() == None && Config->get_auto_return()) || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
401 _transport_frame = last_stop_frame;
403 if (synced_to_jack()) {
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,
444 if (!Config->get_latched_record_enable()) {
445 g_atomic_int_set (&_record_status, Disabled);
447 g_atomic_int_set (&_record_status, Enabled);
449 RecordStateChanged (); /* emit signal */
452 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
453 /* capture start has been changed, so save pending state */
454 save_state ("", true);
458 /* always try to get rid of this */
460 remove_pending_capture_state ();
462 /* save the current state of things if appropriate */
464 if (did_record && !saved) {
465 save_state (_current_snapshot_name);
468 if (post_transport_work & PostTransportDuration) {
469 DurationChanged (); /* EMIT SIGNAL */
472 if (post_transport_work & PostTransportStop) {
475 /* do not turn off autoloop on stop */
479 PositionChanged (_transport_frame); /* EMIT SIGNAL */
480 TransportStateChange (); /* EMIT SIGNAL */
482 /* and start it up again if relevant */
484 if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
485 request_transport_speed (1.0);
486 pending_locate_roll = false;
491 Session::check_declick_out ()
493 bool locate_required = transport_sub_state & PendingLocate;
495 /* this is called after a process() iteration. if PendingDeclickOut was set,
496 it means that we were waiting to declick the output (which has just been
497 done) before doing something else. this is where we do that "something else".
499 note: called from the audio thread.
502 if (transport_sub_state & PendingDeclickOut) {
504 if (locate_required) {
505 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
506 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
508 stop_transport (pending_abort);
509 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
515 Session::set_play_loop (bool yn)
517 /* Called from event-handling context */
519 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
525 if (yn && Config->get_seamless_loop() && synced_to_jack()) {
526 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
527 "Recommend changing the configured options")
533 if ((play_loop = yn)) {
538 if ((loc = _locations.auto_loop_location()) != 0) {
540 if (Config->get_seamless_loop()) {
541 // set all diskstreams to use internal looping
542 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
543 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
544 if (!(*i)->hidden()) {
545 (*i)->set_loop (loc);
550 // set all diskstreams to NOT use internal looping
551 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
552 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
553 if (!(*i)->hidden()) {
559 /* stick in the loop event */
561 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
564 /* locate to start of loop and roll if current pos is outside of the loop range */
565 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
566 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
570 // locate to current position (+ 1 to force reload)
571 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
579 clear_events (Event::AutoLoop);
581 // set all diskstreams to NOT use internal looping
582 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
583 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
584 if (!(*i)->hidden()) {
593 Session::flush_all_redirects ()
595 boost::shared_ptr<RouteList> r = routes.reader ();
597 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
598 (*i)->flush_redirects ();
603 Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
605 if (synced_to_jack()) {
610 _slave->speed_and_position (sp, pos);
612 if (target_frame != pos) {
614 /* tell JACK to change transport position, and we will
615 follow along later in ::follow_slave()
618 _engine.transport_locate (target_frame);
620 if (sp != 1.0f && with_roll) {
621 _engine.transport_start ();
628 locate (target_frame, with_roll, with_flush, with_loop);
633 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
635 if (actively_recording()) {
639 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
641 set_transport_speed (1.0, false);
643 loop_changing = false;
647 _transport_frame = target_frame;
649 if (_transport_speed && (!with_loop || loop_changing)) {
650 /* schedule a declick. we'll be called again when its done */
652 if (!(transport_sub_state & PendingDeclickOut)) {
653 transport_sub_state |= (PendingDeclickOut|PendingLocate);
654 pending_locate_frame = target_frame;
655 pending_locate_roll = with_roll;
656 pending_locate_flush = with_flush;
661 if (transport_rolling() && !Config->get_auto_play() && !with_roll && !(synced_to_jack() && play_loop)) {
662 realtime_stop (false);
665 if ( !with_loop || loop_changing) {
667 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
670 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
673 schedule_butler_transport_work ();
677 /* this is functionally what clear_clicks() does but with a tentative lock */
679 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
681 if (clickm.locked()) {
683 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
692 /* switch from input if we're going to roll */
693 if (Config->get_monitoring_model() == HardwareMonitoring) {
695 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
697 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
698 if ((*i)->record_enabled ()) {
699 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
700 (*i)->monitor_input (!Config->get_auto_input());
705 /* otherwise we're going to stop, so do the opposite */
706 if (Config->get_monitoring_model() == HardwareMonitoring) {
707 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
709 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
710 if ((*i)->record_enabled ()) {
711 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
712 (*i)->monitor_input (true);
718 /* cancel looped playback if transport pos outside of loop range */
720 Location* al = _locations.auto_loop_location();
722 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
723 // cancel looping directly, this is called from event handling context
724 set_play_loop (false);
728 loop_changing = false;
732 Session::set_transport_speed (float speed, bool abort)
734 if (_transport_speed == speed) {
739 speed = min (8.0f, speed);
740 } else if (speed < 0) {
741 speed = max (-8.0f, speed);
744 if (transport_rolling() && speed == 0.0) {
746 if (Config->get_monitoring_model() == HardwareMonitoring)
748 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
750 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
751 if ((*i)->record_enabled ()) {
752 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
753 (*i)->monitor_input (true);
758 if (synced_to_jack ()) {
759 _engine.transport_stop ();
761 stop_transport (abort);
764 } else if (transport_stopped() && speed == 1.0) {
766 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
770 if (Config->get_monitoring_model() == HardwareMonitoring) {
772 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
774 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
775 if (Config->get_auto_input() && (*i)->record_enabled ()) {
776 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
777 (*i)->monitor_input (false);
782 if (synced_to_jack()) {
783 _engine.transport_start ();
790 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
794 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
795 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
800 if (actively_recording()) {
804 if (speed > 0.0f && _transport_frame == current_end_frame()) {
808 if (speed < 0.0f && _transport_frame == 0) {
814 /* if we are reversing relative to the current speed, or relative to the speed
815 before the last stop, then we have to do extra work.
818 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
819 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
822 _last_transport_speed = _transport_speed;
823 _transport_speed = speed;
825 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
826 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
827 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
828 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
832 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
833 schedule_butler_transport_work ();
839 Session::stop_transport (bool abort)
841 if (_transport_speed == 0.0f) {
845 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
846 _worst_output_latency > current_block_size)
849 /* we need to capture the audio that has still not yet been received by the system
850 at the time the stop is requested, so we have to roll past that time.
852 we want to declick before stopping, so schedule the autostop for one
853 block before the actual end. we'll declick in the subsequent block,
854 and then we'll really be stopped.
857 Event *ev = new Event (Event::StopOnce, Event::Replace,
858 _transport_frame + _worst_output_latency - current_block_size,
862 transport_sub_state |= StopPendingCapture;
863 pending_abort = abort;
868 if ((transport_sub_state & PendingDeclickOut) == 0) {
869 transport_sub_state |= PendingDeclickOut;
870 /* we'll be called again after the declick */
871 pending_abort = abort;
875 realtime_stop (abort);
876 schedule_butler_transport_work ();
880 Session::start_transport ()
882 _last_roll_location = _transport_frame;
884 /* if record status is Enabled, move it to Recording. if its
885 already Recording, move it to Disabled.
888 switch (record_status()) {
890 if (!Config->get_punch_in()) {
896 disable_record (false);
903 if (!synced_to_jack() || _exporting) {
904 actually_start_transport ();
906 waiting_to_start = true;
911 Session::actually_start_transport ()
913 waiting_to_start = false;
915 transport_sub_state |= PendingDeclickIn;
916 _transport_speed = 1.0;
918 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
919 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
920 (*i)->realtime_set_speed ((*i)->speed(), true);
923 send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
925 TransportStateChange (); /* EMIT SIGNAL */
929 Session::post_transport ()
931 if (post_transport_work & PostTransportAudition) {
932 if (auditioner && auditioner->active()) {
933 process_function = &Session::process_audition;
935 process_function = &Session::process_with_events;
939 if (post_transport_work & PostTransportStop) {
941 transport_sub_state = 0;
944 if (post_transport_work & PostTransportLocate) {
946 if (((Config->get_slave_source() == None && Config->get_auto_play()) && !_exporting) || (post_transport_work & PostTransportRoll)) {
950 transport_sub_state = 0;
956 post_transport_work = PostTransportWork (0);
960 Session::reset_rf_scale (nframes_t motion)
962 cumulative_rf_motion += motion;
964 if (cumulative_rf_motion < 4 * _current_frame_rate) {
966 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
968 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
980 Session::set_slave_source (SlaveSource src)
982 bool reverse = false;
983 bool non_rt_required = false;
985 if (_transport_speed) {
986 error << _("please stop the transport before adjusting slave settings") << endmsg;
990 // if (src == JACK && Config->get_jack_time_master()) {
999 if (_transport_speed < 0.0) {
1011 _slave = new MTC_Slave (*this, *_mtc_port);
1014 catch (failed_constructor& err) {
1019 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1022 _desired_transport_speed = _transport_speed;
1026 _slave = new JACK_Slave (_engine.jack());
1027 _desired_transport_speed = _transport_speed;
1031 Config->set_slave_source (src);
1033 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1034 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1035 if (!(*i)->hidden()) {
1036 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1037 non_rt_required = true;
1039 (*i)->set_slaved (_slave);
1044 reverse_diskstream_buffers ();
1047 if (non_rt_required) {
1048 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1049 schedule_butler_transport_work ();
1056 Session::reverse_diskstream_buffers ()
1058 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1059 schedule_butler_transport_work ();
1063 Session::set_diskstream_speed (Diskstream* stream, float speed)
1065 if (stream->realtime_set_speed (speed, false)) {
1066 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1067 schedule_butler_transport_work ();
1073 Session::set_audio_range (list<AudioRange>& range)
1075 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1076 ev->audio_range = range;
1081 Session::request_play_range (bool yn)
1083 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1088 Session::set_play_range (bool yn)
1090 /* Called from event-processing context */
1092 if (_play_range != yn) {
1097 /* stop transport */
1098 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1105 Session::setup_auto_play ()
1107 /* Called from event-processing context */
1111 _clear_event_type (Event::RangeStop);
1112 _clear_event_type (Event::RangeLocate);
1118 list<AudioRange>::size_type sz = current_audio_range.size();
1122 list<AudioRange>::iterator i = current_audio_range.begin();
1123 list<AudioRange>::iterator next;
1125 while (i != current_audio_range.end()) {
1130 /* locating/stopping is subject to delays for declicking.
1133 nframes_t requested_frame = (*i).end;
1135 if (requested_frame > current_block_size) {
1136 requested_frame -= current_block_size;
1138 requested_frame = 0;
1141 if (next == current_audio_range.end()) {
1142 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1144 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1152 } else if (sz == 1) {
1154 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1159 /* now start rolling at the right place */
1161 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1166 Session::request_bounded_roll (nframes_t start, nframes_t end)
1169 Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
1171 request_locate (start, true);
1175 Session::engine_halted ()
1179 /* there will be no more calls to process(), so
1180 we'd better clean up for ourselves, right now.
1182 but first, make sure the butler is out of
1186 g_atomic_int_set (&butler_should_do_transport_work, 0);
1187 post_transport_work = PostTransportWork (0);
1190 realtime_stop (false);
1191 non_realtime_stop (false, 0, ignored);
1192 transport_sub_state = 0;
1194 TransportStateChange (); /* EMIT SIGNAL */
1199 Session::xrun_recovery ()
1201 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1203 HaltOnXrun (); /* EMIT SIGNAL */
1205 /* it didn't actually halt, but we need
1206 to handle things in the same way.
1214 Session::update_latency_compensation (bool with_stop, bool abort)
1216 bool update_jack = false;
1218 if (_state_of_the_state & Deletion) {
1222 _worst_track_latency = 0;
1224 boost::shared_ptr<RouteList> r = routes.reader ();
1226 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1228 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1229 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1232 nframes_t old_latency = (*i)->signal_latency ();
1233 nframes_t track_latency = (*i)->update_total_latency ();
1235 if (old_latency != track_latency) {
1239 if (!(*i)->hidden() && ((*i)->active())) {
1240 _worst_track_latency = max (_worst_track_latency, track_latency);
1244 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1245 (*i)->set_latency_delay (_worst_track_latency);
1248 /* tell JACK to play catch up */
1251 _engine.update_total_latencies ();
1254 set_worst_io_latencies ();
1256 /* reflect any changes in latencies into capture offsets
1259 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1261 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1262 (*i)->set_capture_offset ();
1267 Session::update_latency_compensation_proxy (void* ignored)
1269 update_latency_compensation (false, false);