2 Copyright (C) 1999-2002 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 "pbd/error.h"
26 #include "pbd/enumwriter.h"
28 #include <glibmm/threads.h>
30 #include "ardour/audioengine.h"
31 #include "ardour/auditioner.h"
32 #include "ardour/butler.h"
33 #include "ardour/cycle_timer.h"
34 #include "ardour/debug.h"
35 #include "ardour/graph.h"
36 #include "ardour/port.h"
37 #include "ardour/process_thread.h"
38 #include "ardour/scene_changer.h"
39 #include "ardour/session.h"
40 #include "ardour/slave.h"
41 #include "ardour/ticker.h"
42 #include "ardour/types.h"
44 #include "midi++/mmc.h"
48 using namespace ARDOUR;
52 /** Called by the audio engine when there is work to be done with JACK.
53 * @param nframes Number of frames to process.
57 Session::process (pframes_t nframes)
59 framepos_t transport_at_start = _transport_frame;
63 if (processing_blocked()) {
68 if (non_realtime_work_pending()) {
69 if (!_butler->transport_work_requested ()) {
74 _engine.main_thread()->get_buffers ();
76 (this->*process_function) (nframes);
78 _engine.main_thread()->drop_buffers ();
80 /* deliver MIDI clock. Note that we need to use the transport frame
81 * position at the start of process(), not the value at the end of
82 * it. We may already have ticked() because of a transport state
83 * change, for example.
87 if (!_silent && !_engine.freewheeling() && Config->get_send_midi_clock() && (transport_speed() == 1.0f || transport_speed() == 0.0f) && midi_clock->has_midi_port()) {
88 midi_clock->tick (transport_at_start, nframes);
91 _scene_changer->run (transport_at_start, transport_at_start + nframes);
94 /* don't bother with a message */
97 SendFeedback (); /* EMIT SIGNAL */
101 Session::fail_roll (pframes_t nframes)
103 return no_roll (nframes);
107 Session::no_roll (pframes_t nframes)
111 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
113 int declick = get_transport_declick_required();
114 boost::shared_ptr<RouteList> r = routes.reader ();
117 _click_io->silence (nframes);
120 ltc_tx_send_time_code_for_cycle (_transport_frame, end_frame, _target_transport_speed, _transport_speed, nframes);
122 if (_process_graph) {
123 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
124 _process_graph->routes_no_roll( nframes, _transport_frame, end_frame, non_realtime_work_pending(), declick);
126 PT_TIMING_CHECK (10);
127 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
129 if ((*i)->is_auditioner()) {
133 (*i)->set_pending_declick (declick);
135 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending())) {
136 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
141 PT_TIMING_CHECK (11);
148 /** @param need_butler to be set to true by this method if it needs the butler,
149 * otherwise it must be left alone.
152 Session::process_routes (pframes_t nframes, bool& need_butler)
154 int declick = get_transport_declick_required();
155 boost::shared_ptr<RouteList> r = routes.reader ();
157 const framepos_t start_frame = _transport_frame;
158 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
160 if (_process_graph) {
161 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
162 _process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);
165 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
169 if ((*i)->is_auditioner()) {
173 (*i)->set_pending_declick (declick);
177 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, b)) < 0) {
191 /** @param need_butler to be set to true by this method if it needs the butler,
192 * otherwise it must be left alone.
195 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
197 boost::shared_ptr<RouteList> r = routes.reader ();
199 const framepos_t start_frame = _transport_frame;
200 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
202 if (_process_graph) {
203 _process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
205 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
209 if ((*i)->is_auditioner()) {
215 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, b)) < 0) {
230 Session::get_track_statistics ()
235 boost::shared_ptr<RouteList> rl = routes.reader();
236 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
238 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
240 if (!tr || tr->hidden()) {
244 pworst = min (pworst, tr->playback_buffer_load());
245 cworst = min (cworst, tr->capture_buffer_load());
248 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
249 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
251 if (actively_recording()) {
256 /** Process callback used when the auditioner is not active */
258 Session::process_with_events (pframes_t nframes)
263 pframes_t this_nframes;
264 framepos_t end_frame;
265 bool session_needs_butler = false;
266 framecnt_t frames_moved;
268 /* make sure the auditioner is silent */
271 auditioner->silence (nframes);
274 /* handle any pending events */
276 while (pending_events.read (&ev, 1) == 1) {
280 /* if we are not in the middle of a state change,
281 and there are immediate events queued up,
285 while (!non_realtime_work_pending() && !immediate_events.empty()) {
286 SessionEvent *ev = immediate_events.front ();
287 immediate_events.pop_front ();
291 /* Decide on what to do with quarter-frame MTC during this cycle */
293 bool const was_sending_qf_mtc = _send_qf_mtc;
294 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
296 if (_transport_speed != 0) {
298 Config->get_send_mtc () &&
299 _transport_speed >= (1 - tolerance) &&
300 _transport_speed <= (1 + tolerance)
303 if (_send_qf_mtc && !was_sending_qf_mtc) {
304 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
305 _send_timecode_update = true;
308 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
309 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
310 a quarter of a second since we sent anything at all, so send a full MTC update
313 _send_timecode_update = true;
316 _pframes_since_last_mtc += nframes;
319 /* Events caused a transport change (or we re-started sending
320 * MTC), so send an MTC Full Frame (Timecode) message. This
321 * is sent whether rolling or not, to give slaves an idea of
322 * ardour time on locates (and allow slow slaves to position
323 * and prepare for rolling)
325 if (_send_timecode_update) {
326 send_full_time_code (_transport_frame, nframes);
329 if (!process_can_proceed()) {
334 if (events.empty() || next_event == events.end()) {
335 process_without_events (nframes);
339 if (_transport_speed == 1.0) {
340 frames_moved = (framecnt_t) nframes;
342 interpolation.set_target_speed (_target_transport_speed);
343 interpolation.set_speed (_transport_speed);
344 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
347 end_frame = _transport_frame + frames_moved;
350 SessionEvent* this_event;
351 Events::iterator the_next_one;
353 if (!process_can_proceed()) {
358 if (!_exporting && _slave) {
359 if (!follow_slave (nframes)) {
364 if (_transport_speed == 0) {
369 if (!_exporting && !timecode_transmission_suspended()) {
370 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
373 framepos_t stop_limit = compute_stop_limit ();
375 if (maybe_stop (stop_limit)) {
380 this_event = *next_event;
381 the_next_one = next_event;
384 /* yes folks, here it is, the actual loop where we really truly
390 this_nframes = nframes; /* real (jack) time relative */
391 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
393 /* running an event, position transport precisely to its time */
394 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
395 /* this isn't quite right for reverse play */
396 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
397 this_nframes = abs (floor(frames_moved / _transport_speed));
402 click (_transport_frame, this_nframes);
404 if (process_routes (this_nframes, session_needs_butler)) {
409 get_track_statistics ();
411 nframes -= this_nframes;
413 if (frames_moved < 0) {
414 decrement_transport_position (-frames_moved);
416 increment_transport_position (frames_moved);
419 maybe_stop (stop_limit);
420 check_declick_out ();
424 _engine.split_cycle (this_nframes);
427 /* now handle this event and all others scheduled for the same time */
429 while (this_event && this_event->action_frame == _transport_frame) {
430 process_event (this_event);
432 if (the_next_one == events.end()) {
435 this_event = *the_next_one;
440 /* if an event left our state changing, do the right thing */
442 if (nframes && non_realtime_work_pending()) {
447 /* this is necessary to handle the case of seamless looping */
448 end_frame = _transport_frame + floor (nframes * _transport_speed);
453 } /* implicit release of route lock */
455 if (session_needs_butler) {
461 Session::reset_slave_state ()
463 average_slave_delta = 1800;
464 delta_accumulator_cnt = 0;
465 have_first_delta_accumulator = false;
466 _slave_state = Stopped;
470 Session::transport_locked () const
474 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
482 Session::follow_slave (pframes_t nframes)
485 framepos_t slave_transport_frame;
486 framecnt_t this_delta;
491 config.set_external_sync (false);
495 _slave->speed_and_position (slave_speed, slave_transport_frame);
497 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
499 if (!_slave->locked()) {
500 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
504 if (slave_transport_frame > _transport_frame) {
505 this_delta = slave_transport_frame - _transport_frame;
508 this_delta = _transport_frame - slave_transport_frame;
512 if (_slave->starting()) {
516 if (_slave->is_always_synced() ||
517 (Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
520 /* if the TC source is synced, then we assume that its
521 speed is binary: 0.0 or 1.0
524 if (slave_speed != 0.0f) {
530 /* if we are chasing and the average delta between us and the
531 master gets too big, we want to switch to silent
532 motion. so keep track of that here.
535 if (_slave_state == Running) {
536 calculate_moving_average_of_slave_delta(dir, this_delta);
540 track_slave_state (slave_speed, slave_transport_frame, this_delta);
542 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
543 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
546 if (_slave_state == Running && !_slave->is_always_synced() &&
547 !(Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
550 if (_transport_speed != 0.0f) {
553 note that average_dir is +1 or -1
558 if (average_slave_delta == 0) {
562 delta = average_slave_delta;
563 delta *= average_dir;
567 if (slave_speed != 0.0) {
568 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
569 (int) (dir * this_delta),
573 slave_transport_frame,
574 average_slave_delta));
578 if (_slave->give_slave_full_control_over_transport_speed()) {
579 set_transport_speed (slave_speed, 0, false, false);
580 //std::cout << "set speed = " << slave_speed << "\n";
582 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
583 request_transport_speed (adjusted_speed);
584 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
585 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
590 if (!actively_recording() && (framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
591 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
599 if (_slave_state == Running && !non_realtime_work_pending()) {
600 /* speed is set, we're locked, and good to go */
605 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
606 follow_slave_silently (nframes, slave_speed);
609 /* don't move at all */
610 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
616 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
618 if (delta_accumulator_cnt >= delta_accumulator_size) {
619 have_first_delta_accumulator = true;
620 delta_accumulator_cnt = 0;
623 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
624 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
627 if (have_first_delta_accumulator) {
628 average_slave_delta = 0L;
629 for (int i = 0; i < delta_accumulator_size; ++i) {
630 average_slave_delta += delta_accumulator[i];
632 average_slave_delta /= (int32_t) delta_accumulator_size;
633 if (average_slave_delta < 0L) {
635 average_slave_delta = abs(average_slave_delta);
643 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t /*this_delta*/)
645 if (slave_speed != 0.0f) {
647 /* slave is running */
649 switch (_slave_state) {
651 if (_slave->requires_seekahead()) {
652 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
653 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
654 /* we can call locate() here because we are in process context */
655 locate (slave_wait_end, false, false);
656 _slave_state = Waiting;
660 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped -> running at %1\n", slave_transport_frame));
662 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
663 average_slave_delta = 0L;
665 Location* al = _locations->auto_loop_location();
667 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
669 request_play_loop(false);
672 if (slave_transport_frame != _transport_frame) {
673 DEBUG_TRACE (DEBUG::Slave, string_compose ("require locate to run. eng: %1 -> sl: %2\n", _transport_frame, slave_transport_frame));
674 locate (slave_transport_frame, false, false);
676 _slave_state = Running;
685 if (_slave_state == Waiting) {
687 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
689 if (slave_transport_frame >= slave_wait_end) {
691 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
693 _slave_state = Running;
695 /* now perform a "micro-seek" within the disk buffers to realign ourselves
696 precisely with the master.
701 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
703 boost::shared_ptr<RouteList> rl = routes.reader();
704 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
705 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
706 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
713 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
714 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
716 tr->internal_playback_seek (frame_delta);
719 _transport_frame += frame_delta;
722 cerr << "cannot micro-seek\n";
728 if (_slave_state == Running && _transport_speed == 0.0f) {
729 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
733 } else { // slave_speed is 0
735 /* slave has stopped */
737 if (_transport_speed != 0.0f) {
738 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
742 if (slave_transport_frame != _transport_frame) {
743 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
744 force_locate (slave_transport_frame, false);
752 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
754 if (slave_speed && _transport_speed) {
756 /* something isn't right, but we should move with the master
762 silent_process_routes (nframes, need_butler);
764 get_track_statistics ();
770 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
772 if (frames_moved < 0) {
773 decrement_transport_position (-frames_moved);
775 increment_transport_position (frames_moved);
778 framepos_t const stop_limit = compute_stop_limit ();
779 maybe_stop (stop_limit);
784 Session::process_without_events (pframes_t nframes)
786 bool session_needs_butler = false;
787 framecnt_t frames_moved;
789 if (!process_can_proceed()) {
794 if (!_exporting && _slave) {
795 if (!follow_slave (nframes)) {
796 ltc_tx_send_time_code_for_cycle (_transport_frame, _transport_frame, 0, 0 , nframes);
801 if (_transport_speed == 0) {
806 if (_transport_speed == 1.0) {
807 frames_moved = (framecnt_t) nframes;
809 interpolation.set_target_speed (_target_transport_speed);
810 interpolation.set_speed (_transport_speed);
811 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
814 if (!_exporting && !timecode_transmission_suspended()) {
815 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
818 ltc_tx_send_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, _target_transport_speed, _transport_speed, nframes);
820 framepos_t const stop_limit = compute_stop_limit ();
822 if (maybe_stop (stop_limit)) {
827 if (maybe_sync_start (nframes)) {
831 click (_transport_frame, nframes);
833 if (process_routes (nframes, session_needs_butler)) {
838 get_track_statistics ();
840 if (frames_moved < 0) {
841 decrement_transport_position (-frames_moved);
843 increment_transport_position (frames_moved);
846 maybe_stop (stop_limit);
847 check_declick_out ();
849 if (session_needs_butler) {
854 /** Process callback used when the auditioner is active.
855 * @param nframes number of frames to process.
858 Session::process_audition (pframes_t nframes)
861 boost::shared_ptr<RouteList> r = routes.reader ();
863 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
864 if (!(*i)->is_auditioner()) {
865 (*i)->silence (nframes);
869 /* run the auditioner, and if it says we need butler service, ask for it */
871 if (auditioner->play_audition (nframes) > 0) {
875 /* if using a monitor section, run it because otherwise we don't hear anything */
877 if (_monitor_out && auditioner->needs_monitor()) {
878 _monitor_out->monitor_run (_transport_frame, _transport_frame + nframes, nframes, false);
881 /* handle pending events */
883 while (pending_events.read (&ev, 1) == 1) {
887 /* if we are not in the middle of a state change,
888 and there are immediate events queued up,
892 while (!non_realtime_work_pending() && !immediate_events.empty()) {
893 SessionEvent *ev = immediate_events.front ();
894 immediate_events.pop_front ();
898 if (!auditioner->auditioning()) {
899 /* auditioner no longer active, so go back to the normal process callback */
900 process_function = &Session::process_with_events;
905 Session::maybe_sync_start (pframes_t & nframes)
907 pframes_t sync_offset;
909 if (!waiting_for_sync_offset) {
913 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
915 /* generate silence up to the sync point, then
916 adjust nframes + offset to reflect whatever
920 no_roll (sync_offset);
921 nframes -= sync_offset;
922 Port::increment_global_port_buffer_offset (sync_offset);
923 waiting_for_sync_offset = false;
926 return true; // done, nothing left to process
931 /* sync offset point is not within this process()
932 cycle, so just generate silence. and don't bother
933 with any fancy stuff here, just the minimal silence.
938 if (Config->get_locate_while_waiting_for_sync()) {
939 if (micro_locate (nframes)) {
940 /* XXX ERROR !!! XXX */
944 return true; // done, nothing left to process
951 Session::queue_event (SessionEvent* ev)
953 if (_state_of_the_state & Deletion) {
955 } else if (_state_of_the_state & Loading) {
958 pending_events.write (&ev, 1);
963 Session::set_next_event ()
965 if (events.empty()) {
966 next_event = events.end();
970 if (next_event == events.end()) {
971 next_event = events.begin();
974 if ((*next_event)->action_frame > _transport_frame) {
975 next_event = events.begin();
978 for (; next_event != events.end(); ++next_event) {
979 if ((*next_event)->action_frame >= _transport_frame) {
986 Session::process_event (SessionEvent* ev)
991 /* if we're in the middle of a state change (i.e. waiting
992 for the butler thread to complete the non-realtime
993 part of the change), we'll just have to queue this
994 event for a time when the change is complete.
997 if (non_realtime_work_pending()) {
999 /* except locates, which we have the capability to handle */
1001 if (ev->type != SessionEvent::Locate) {
1002 immediate_events.insert (immediate_events.end(), ev);
1008 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1011 case SessionEvent::SetLoop:
1012 set_play_loop (ev->yes_or_no, ev->speed);
1015 case SessionEvent::AutoLoop:
1017 /* roll after locate, do not flush, set "with loop"
1018 true only if we are seamless looping
1020 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1026 case SessionEvent::AutoLoopDeclick:
1028 /* Request a declick fade-out and a fade-in; the fade-out will happen
1029 at the end of the loop, and the fade-in at the start.
1031 transport_sub_state |= (PendingLoopDeclickOut | PendingLoopDeclickIn);
1037 case SessionEvent::Locate:
1038 if (ev->yes_or_no) {
1039 /* args: do not roll after locate, do flush, not with loop */
1040 locate (ev->target_frame, false, true, false);
1042 /* args: do not roll after locate, do flush, not with loop */
1043 start_locate (ev->target_frame, false, true, false);
1045 _send_timecode_update = true;
1048 case SessionEvent::LocateRoll:
1049 if (ev->yes_or_no) {
1050 /* args: roll after locate, do flush, not with loop */
1051 locate (ev->target_frame, true, true, false);
1053 /* args: roll after locate, do flush, not with loop */
1054 start_locate (ev->target_frame, true, true, false);
1056 _send_timecode_update = true;
1059 case SessionEvent::Skip:
1060 if (Config->get_skip_playback()) {
1061 start_locate (ev->target_frame, true, true, false);
1062 _send_timecode_update = true;
1068 case SessionEvent::LocateRollLocate:
1069 // locate is handled by ::request_roll_at_and_return()
1070 _requested_return_frame = ev->target_frame;
1071 request_locate (ev->target2_frame, true);
1075 case SessionEvent::SetTransportSpeed:
1076 set_transport_speed (ev->speed, ev->target_frame, ev->yes_or_no, ev->second_yes_or_no, ev->third_yes_or_no);
1079 case SessionEvent::PunchIn:
1080 // cerr << "PunchIN at " << transport_frame() << endl;
1081 if (config.get_punch_in() && record_status() == Enabled) {
1088 case SessionEvent::PunchOut:
1089 // cerr << "PunchOUT at " << transport_frame() << endl;
1090 if (config.get_punch_out()) {
1091 step_back_from_record ();
1097 case SessionEvent::StopOnce:
1098 if (!non_realtime_work_pending()) {
1099 _clear_event_type (SessionEvent::StopOnce);
1100 stop_transport (ev->yes_or_no);
1106 case SessionEvent::RangeStop:
1107 if (!non_realtime_work_pending()) {
1108 stop_transport (ev->yes_or_no);
1114 case SessionEvent::RangeLocate:
1115 /* args: roll after locate, do flush, not with loop */
1116 start_locate (ev->target_frame, true, true, false);
1121 case SessionEvent::Overwrite:
1122 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1125 case SessionEvent::SetTrackSpeed:
1126 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1129 case SessionEvent::SetSyncSource:
1130 DEBUG_TRACE (DEBUG::Slave, "seen request for new slave\n");
1131 use_sync_source (ev->slave);
1134 case SessionEvent::Audition:
1135 set_audition (ev->region);
1136 // drop reference to region
1137 ev->region.reset ();
1140 case SessionEvent::InputConfigurationChange:
1141 add_post_transport_work (PostTransportInputChange);
1142 _butler->schedule_transport_work ();
1145 case SessionEvent::SetPlayAudioRange:
1146 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1149 case SessionEvent::CancelPlayAudioRange:
1153 case SessionEvent::RealTimeOperation:
1155 del = false; // other side of RT request needs to clean up
1158 case SessionEvent::AdjustPlaybackBuffering:
1159 schedule_playback_buffering_adjustment ();
1162 case SessionEvent::AdjustCaptureBuffering:
1163 schedule_capture_buffering_adjustment ();
1166 case SessionEvent::SetTimecodeTransmission:
1167 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1171 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1172 abort(); /*NOTREACHED*/
1177 del = del && !_remove_event (ev);
1186 Session::compute_stop_limit () const
1188 if (!Config->get_stop_at_session_end ()) {
1189 return max_framepos;
1193 return max_framepos;
1197 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1198 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1200 if (actively_recording ()) {
1201 /* permanently recording */
1202 return max_framepos;
1203 } else if (punching_in && !punching_out) {
1204 /* punching in but never out */
1205 return max_framepos;
1206 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_frame()) {
1207 /* punching in and punching out after session end */
1208 return max_framepos;
1211 return current_end_frame ();