2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sigc++/bind.h>
26 #include <sigc++/retype.h>
29 #include <pbd/error.h>
30 #include <glibmm/thread.h>
31 #include <pbd/pthread_utils.h>
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 Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
59 Session::request_slave_source (SlaveSource src, jack_nframes_t pos)
61 Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, pos, 0.0);
63 if (src == Session::JACK) {
64 /* could set_seamless_loop() be disposed of entirely?*/
65 set_seamless_loop (false);
68 set_seamless_loop (true);
75 Session::request_transport_speed (float speed)
77 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
82 Session::request_diskstream_speed (Diskstream& ds, float speed)
84 Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
90 Session::request_stop (bool abort)
92 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
97 Session::request_locate (jack_nframes_t target_frame, bool with_roll)
99 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
104 Session::force_locate (jack_nframes_t target_frame, bool with_roll)
106 Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
111 Session::request_auto_loop (bool yn)
114 Location *location = _locations.auto_loop_location();
116 if (location == 0 && yn) {
117 error << _("Cannot loop - no loop range defined")
122 ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
125 if (!yn && seamless_loop && transport_rolling()) {
126 // request an immediate locate to refresh the diskstreams
127 // after disabling looping
128 request_locate (_transport_frame-1, true);
133 Session::set_seamless_loop (bool yn)
135 if (seamless_loop != yn) {
138 if (auto_loop && transport_rolling()) {
139 // to reset diskstreams etc
140 request_auto_loop (true);
143 ControlChanged (SeamlessLoop); /* EMIT */
148 Session::realtime_stop (bool abort)
150 /* assume that when we start, we'll be moving forwards */
152 // FIXME: where should this really be? [DR]
153 //send_full_time_code();
154 deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
155 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
157 if (_transport_speed < 0.0f) {
158 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
160 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
163 if (actively_recording()) {
165 /* move the transport position back to where the
166 request for a stop was noticed. we rolled
167 past that point to pick up delayed input.
170 #ifndef LEAVE_TRANSPORT_UNADJUSTED
171 decrement_transport_position (_worst_output_latency);
174 /* the duration change is not guaranteed to have happened, but is likely */
176 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
180 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
183 _clear_event_type (Event::StopOnce);
184 _clear_event_type (Event::RangeStop);
185 _clear_event_type (Event::RangeLocate);
187 disable_record (true);
189 reset_slave_state ();
191 _transport_speed = 0;
193 transport_sub_state = (auto_return ? AutoReturning : 0);
197 Session::butler_transport_work ()
199 Glib::RWLock::ReaderLock dsm (diskstream_lock);
200 boost::shared_ptr<RouteList> r = routes.reader ();
202 if (post_transport_work & PostTransportCurveRealloc) {
203 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
204 (*i)->curve_reallocate();
208 if (post_transport_work & PostTransportInputChange) {
209 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
210 (*i)->non_realtime_input_change ();
214 if (post_transport_work & PostTransportSpeed) {
215 non_realtime_set_speed ();
218 if (post_transport_work & PostTransportReverse) {
222 cumulative_rf_motion = 0;
225 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
226 if (!(*i)->hidden()) {
227 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
228 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
231 (*i)->seek (_transport_frame);
237 if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
238 non_realtime_stop (post_transport_work & PostTransportAbort);
241 if (post_transport_work & PostTransportOverWrite) {
242 non_realtime_overwrite ();
245 if (post_transport_work & PostTransportAudition) {
246 non_realtime_set_audition ();
249 g_atomic_int_dec_and_test (&butler_should_do_transport_work);
253 Session::non_realtime_set_speed ()
255 Glib::RWLock::ReaderLock lm (diskstream_lock);
257 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
258 (*i)->non_realtime_set_speed ();
263 Session::non_realtime_overwrite ()
265 Glib::RWLock::ReaderLock lm (diskstream_lock);
267 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
268 if ((*i)->pending_overwrite) {
269 (*i)->overwrite_existing_buffers ();
275 Session::non_realtime_stop (bool abort)
283 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
284 if ((*i)->get_captured_frames () != 0) {
290 /* stop and locate are merged here because they share a lot of common stuff */
293 now = localtime (&xnow);
296 auditioner->cancel_audition ();
300 cumulative_rf_motion = 0;
304 begin_reversible_command ("capture");
306 Location* loc = _locations.end_location();
307 bool change_end = false;
309 if (_transport_frame < loc->end()) {
311 /* stopped recording before current end */
313 if (_end_location_is_free) {
315 /* first capture for this session, move end back to where we are */
320 } else if (_transport_frame > loc->end()) {
322 /* stopped recording after the current end, extend it */
328 add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
329 add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
332 _end_location_is_free = false;
333 _have_captured = true;
336 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
337 (*i)->transport_stopped (*now, xnow, abort);
340 boost::shared_ptr<RouteList> r = routes.reader ();
342 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
343 if (!(*i)->hidden()) {
344 (*i)->set_pending_declick (0);
349 commit_reversible_command ();
352 if (_engine.running()) {
353 update_latency_compensation (true, abort);
356 if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
358 if (pending_locate_flush) {
359 flush_all_redirects ();
362 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
364 _transport_frame = last_stop_frame;
366 if (synced_to_jack()) {
367 _engine.transport_locate (_transport_frame);
371 #ifndef LEAVE_TRANSPORT_UNADJUSTED
375 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
376 if (!(*i)->hidden()) {
377 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
378 (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
381 (*i)->seek (_transport_frame);
387 //deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
389 #ifdef LEAVE_TRANSPORT_UNADJUSTED
393 last_stop_frame = _transport_frame;
397 /* XXX its a little odd that we're doing this here
398 when realtime_stop(), which has already executed,
402 if (!Config->get_latched_record_enable()) {
403 g_atomic_int_set (&_record_status, Disabled);
405 g_atomic_int_set (&_record_status, Enabled);
407 RecordStateChanged (); /* emit signal */
410 if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
411 /* capture start has been changed, so save pending state */
412 save_state ("", true);
415 /* always try to get rid of this */
417 remove_pending_capture_state ();
419 /* save the current state of things if appropriate */
422 save_state (_current_snapshot_name);
425 if (post_transport_work & PostTransportDuration) {
426 DurationChanged (); /* EMIT SIGNAL */
429 if (post_transport_work & PostTransportStop) {
432 /* do not turn off autoloop on stop */
436 PositionChanged (_transport_frame); /* EMIT SIGNAL */
437 TransportStateChange (); /* EMIT SIGNAL */
439 /* and start it up again if relevant */
441 if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
442 request_transport_speed (1.0);
443 pending_locate_roll = false;
448 Session::check_declick_out ()
450 bool locate_required = transport_sub_state & PendingLocate;
452 /* this is called after a process() iteration. if PendingDeclickOut was set,
453 it means that we were waiting to declick the output (which has just been
454 done) before doing something else. this is where we do that "something else".
456 note: called from the audio thread.
459 if (transport_sub_state & PendingDeclickOut) {
461 if (locate_required) {
462 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
463 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
465 stop_transport (pending_abort);
466 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
472 Session::set_auto_loop (bool yn)
474 /* Called from event-handling context */
476 if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
482 if (yn && seamless_loop && synced_to_jack()) {
483 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
484 "Recommend changing the configured options")
490 if ((auto_loop = yn)) {
495 if ((loc = _locations.auto_loop_location()) != 0) {
498 // set all diskstreams to use internal looping
499 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
500 if (!(*i)->hidden()) {
501 (*i)->set_loop (loc);
506 // set all diskstreams to NOT use internal looping
507 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
508 if (!(*i)->hidden()) {
514 /* stick in the loop event */
516 Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
519 /* locate to start of loop and roll if current pos is outside of the loop range */
520 if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
521 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
525 // locate to current position (+ 1 to force reload)
526 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
534 clear_events (Event::AutoLoop);
536 // set all diskstreams to NOT use internal looping
537 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
538 if (!(*i)->hidden()) {
545 ControlChanged (AutoLoop); /* EMIT SIGNAL */
549 Session::flush_all_redirects ()
551 boost::shared_ptr<RouteList> r = routes.reader ();
553 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
554 (*i)->flush_redirects ();
559 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
561 if (synced_to_jack()) {
566 _slave->speed_and_position (sp, pos);
568 if (target_frame != pos) {
570 /* tell JACK to change transport position, and we will
571 follow along later in ::follow_slave()
574 _engine.transport_locate (target_frame);
576 if (sp != 1.0f && with_roll) {
577 _engine.transport_start ();
584 locate (target_frame, with_roll, with_flush, with_loop);
589 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
591 if (actively_recording()) {
595 if (_transport_frame == target_frame && !loop_changing && !with_loop) {
597 set_transport_speed (1.0, false);
599 loop_changing = false;
604 // [DR] FIXME: find out exactly where this should go below
605 _transport_frame = target_frame;
606 smpte_time(_transport_frame, transmitting_smpte_time);
607 outbound_mtc_smpte_frame = _transport_frame;
608 next_quarter_frame_to_send = 0;
610 if (_transport_speed && (!with_loop || loop_changing)) {
611 /* schedule a declick. we'll be called again when its done */
613 if (!(transport_sub_state & PendingDeclickOut)) {
614 transport_sub_state |= (PendingDeclickOut|PendingLocate);
615 pending_locate_frame = target_frame;
616 pending_locate_roll = with_roll;
617 pending_locate_flush = with_flush;
622 if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
623 realtime_stop (false);
626 if ( !with_loop || loop_changing) {
628 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
631 post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
634 schedule_butler_transport_work ();
638 /* this is functionally what clear_clicks() does but with a tentative lock */
640 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
642 if (clickm.locked()) {
644 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
653 /* switch from input if we're going to roll */
654 if (Config->get_use_hardware_monitoring()) {
655 /* Even though this is called from RT context we are using
656 a non-tentative rwlock here, because the action must occur.
657 The rarity and short potential lock duration makes this "OK"
659 Glib::RWLock::ReaderLock dsm (diskstream_lock);
660 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
661 if ((*i)->record_enabled ()) {
662 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
663 (*i)->monitor_input (!auto_input);
668 /* otherwise we're going to stop, so do the opposite */
669 if (Config->get_use_hardware_monitoring()) {
670 /* Even though this is called from RT context we are using
671 a non-tentative rwlock here, because the action must occur.
672 The rarity and short potential lock duration makes this "OK"
674 Glib::RWLock::ReaderLock dsm (diskstream_lock);
675 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
676 if ((*i)->record_enabled ()) {
677 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
678 (*i)->monitor_input (true);
684 /* cancel autoloop if transport pos outside of loop range */
686 Location* al = _locations.auto_loop_location();
688 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
689 // cancel looping directly, this is called from event handling context
690 set_auto_loop(false);
694 loop_changing = false;
696 _send_smpte_update = true;
700 Session::set_transport_speed (float speed, bool abort)
702 if (_transport_speed == speed) {
707 speed = min (8.0f, speed);
708 } else if (speed < 0) {
709 speed = max (-8.0f, speed);
712 if (transport_rolling() && speed == 0.0) {
714 if (Config->get_use_hardware_monitoring())
716 /* Even though this is called from RT context we are using
717 a non-tentative rwlock here, because the action must occur.
718 The rarity and short potential lock duration makes this "OK"
720 Glib::RWLock::ReaderLock dsm (diskstream_lock);
721 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
722 if ((*i)->record_enabled ()) {
723 //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
724 (*i)->monitor_input (true);
729 if (synced_to_jack ()) {
730 _engine.transport_stop ();
732 stop_transport (abort);
735 } else if (transport_stopped() && speed == 1.0) {
737 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
741 if (Config->get_use_hardware_monitoring()) {
742 /* Even though this is called from RT context we are using
743 a non-tentative rwlock here, because the action must occur.
744 The rarity and short potential lock duration makes this "OK"
746 Glib::RWLock::ReaderLock dsm (diskstream_lock);
747 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
748 if (auto_input && (*i)->record_enabled ()) {
749 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
750 (*i)->monitor_input (false);
755 if (synced_to_jack()) {
756 _engine.transport_start ();
763 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
767 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
768 warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
773 if (actively_recording()) {
777 if (speed > 0.0f && _transport_frame == current_end_frame()) {
781 if (speed < 0.0f && _transport_frame == 0) {
787 /* if we are reversing relative to the current speed, or relative to the speed
788 before the last stop, then we have to do extra work.
791 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
792 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
795 _last_transport_speed = _transport_speed;
796 _transport_speed = speed;
798 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
799 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
800 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
804 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
805 schedule_butler_transport_work ();
811 Session::stop_transport (bool abort)
813 if (_transport_speed == 0.0f) {
817 if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
818 _worst_output_latency > current_block_size)
821 /* we need to capture the audio that has still not yet been received by the system
822 at the time the stop is requested, so we have to roll past that time.
824 we want to declick before stopping, so schedule the autostop for one
825 block before the actual end. we'll declick in the subsequent block,
826 and then we'll really be stopped.
829 Event *ev = new Event (Event::StopOnce, Event::Replace,
830 _transport_frame + _worst_output_latency - current_block_size,
834 transport_sub_state |= StopPendingCapture;
835 pending_abort = abort;
839 if ((transport_sub_state & PendingDeclickOut) == 0) {
840 transport_sub_state |= PendingDeclickOut;
841 /* we'll be called again after the declick */
845 realtime_stop (abort);
846 schedule_butler_transport_work ();
850 Session::start_transport ()
852 _last_roll_location = _transport_frame;
854 /* if record status is Enabled, move it to Recording. if its
855 already Recording, move it to Disabled.
858 switch (record_status()) {
866 disable_record (false);
873 if (!synced_to_jack() || _exporting) {
874 actually_start_transport ();
876 waiting_to_start = true;
881 Session::actually_start_transport ()
883 waiting_to_start = false;
885 transport_sub_state |= PendingDeclickIn;
886 _transport_speed = 1.0;
888 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
889 (*i)->realtime_set_speed ((*i)->speed(), true);
892 deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
894 TransportStateChange (); /* EMIT SIGNAL */
897 /** Do any transport work in the audio thread that needs to be done after the
898 * transport thread is finished. Audio thread, realtime safe.
901 Session::post_transport ()
903 if (post_transport_work & PostTransportAudition) {
904 if (auditioner && auditioner->active()) {
905 process_function = &Session::process_audition;
907 process_function = &Session::process_with_events;
911 if (post_transport_work & PostTransportStop) {
913 transport_sub_state = 0;
916 if (post_transport_work & PostTransportLocate) {
918 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
923 transport_sub_state = 0;
929 post_transport_work = PostTransportWork (0);
933 Session::set_rf_speed (float speed)
936 cumulative_rf_motion = 0;
941 Session::reset_rf_scale (jack_nframes_t motion)
943 cumulative_rf_motion += motion;
945 if (cumulative_rf_motion < 4 * _current_frame_rate) {
947 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
949 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
961 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
963 bool reverse = false;
964 bool non_rt_required = false;
966 if (src == _slave_type) {
970 if (_transport_speed) {
971 error << _("please stop the transport before adjusting slave settings") << endmsg;
972 /* help out non-MVC friendly UI's by telling them the slave type changed */
973 ControlChanged (SlaveType); /* EMIT SIGNAL */
977 // if (src == JACK && Config->get_jack_time_master()) {
987 if (_transport_speed < 0.0) {
999 _slave = new MTC_Slave (*this, *_mtc_port);
1002 catch (failed_constructor& err) {
1007 error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1010 _desired_transport_speed = _transport_speed;
1014 _slave = new JACK_Slave (_engine.jack());
1015 _desired_transport_speed = _transport_speed;
1021 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1022 if (!(*i)->hidden()) {
1023 if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1024 non_rt_required = true;
1026 (*i)->set_slaved (_slave);
1031 reverse_diskstream_buffers ();
1034 if (non_rt_required) {
1035 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1036 schedule_butler_transport_work ();
1040 ControlChanged (SlaveType); /* EMIT SIGNAL */
1046 Session::reverse_diskstream_buffers ()
1048 post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1049 schedule_butler_transport_work ();
1053 Session::set_diskstream_speed (Diskstream* stream, float speed)
1055 if (stream->realtime_set_speed (speed, false)) {
1056 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1057 schedule_butler_transport_work ();
1063 Session::set_audio_range (list<AudioRange>& range)
1065 Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1066 ev->audio_range = range;
1071 Session::request_play_range (bool yn)
1073 Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1078 Session::set_play_range (bool yn)
1080 /* Called from event-processing context */
1082 if (_play_range != yn) {
1087 /* stop transport */
1088 Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1092 ControlChanged (PlayRange); /* EMIT SIGNAL */
1097 Session::setup_auto_play ()
1099 /* Called from event-processing context */
1103 _clear_event_type (Event::RangeStop);
1104 _clear_event_type (Event::RangeLocate);
1110 list<AudioRange>::size_type sz = current_audio_range.size();
1114 list<AudioRange>::iterator i = current_audio_range.begin();
1115 list<AudioRange>::iterator next;
1117 while (i != current_audio_range.end()) {
1122 /* locating/stopping is subject to delays for declicking.
1125 jack_nframes_t requested_frame = (*i).end;
1127 if (requested_frame > current_block_size) {
1128 requested_frame -= current_block_size;
1130 requested_frame = 0;
1133 if (next == current_audio_range.end()) {
1134 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1136 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1144 } else if (sz == 1) {
1146 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1151 /* now start rolling at the right place */
1153 ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1158 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1161 Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1163 request_locate (start, true);
1167 Session::engine_halted ()
1169 /* there will be no more calls to process(), so
1170 we'd better clean up for ourselves, right now.
1172 but first, make sure the butler is out of
1176 g_atomic_int_set (&butler_should_do_transport_work, 0);
1177 post_transport_work = PostTransportWork (0);
1180 realtime_stop (false);
1181 non_realtime_stop (false);
1182 transport_sub_state = 0;
1184 TransportStateChange (); /* EMIT SIGNAL */
1189 Session::xrun_recovery ()
1191 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1193 HaltOnXrun (); /* EMIT SIGNAL */
1195 /* it didn't actually halt, but we need
1196 to handle things in the same way.
1204 Session::update_latency_compensation (bool with_stop, bool abort)
1206 bool update_jack = false;
1208 if (_state_of_the_state & Deletion) {
1212 Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1213 _worst_track_latency = 0;
1215 boost::shared_ptr<RouteList> r = routes.reader ();
1217 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1219 (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
1220 (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1223 jack_nframes_t old_latency = (*i)->signal_latency ();
1224 jack_nframes_t track_latency = (*i)->update_total_latency ();
1226 if (old_latency != track_latency) {
1230 if (!(*i)->hidden() && ((*i)->active())) {
1231 _worst_track_latency = max (_worst_track_latency, track_latency);
1235 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1236 (*i)->set_latency_delay (_worst_track_latency);
1239 /* tell JACK to play catch up */
1242 _engine.update_total_latencies ();
1245 set_worst_io_latencies ();
1247 /* reflect any changes in latencies into capture offsets
1250 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1251 (*i)->set_capture_offset ();
1256 Session::update_latency_compensation_proxy (void* ignored)
1258 update_latency_compensation (false, false);