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/session.h"
39 #include "ardour/slave.h"
40 #include "ardour/ticker.h"
41 #include "ardour/types.h"
43 #include "midi++/mmc.h"
47 using namespace ARDOUR;
51 /** Called by the audio engine when there is work to be done with JACK.
52 * @param nframes Number of frames to process.
56 Session::process (pframes_t nframes)
58 framepos_t transport_at_start = _transport_frame;
62 if (processing_blocked()) {
67 if (non_realtime_work_pending()) {
68 if (!_butler->transport_work_requested ()) {
73 _engine.main_thread()->get_buffers ();
75 (this->*process_function) (nframes);
77 _engine.main_thread()->drop_buffers ();
79 /* deliver MIDI clock. Note that we need to use the transport frame
80 * position at the start of process(), not the value at the end of
81 * it. We may already have ticked() because of a transport state
82 * change, for example.
86 if (!_silent && !_engine.freewheeling() && Config->get_send_midi_clock() && (transport_speed() == 1.0f || transport_speed() == 0.0f) && midi_clock->has_midi_port()) {
87 midi_clock->tick (transport_at_start, nframes);
90 /* don't bother with a message */
93 SendFeedback (); /* EMIT SIGNAL */
97 Session::fail_roll (pframes_t nframes)
99 return no_roll (nframes);
103 Session::no_roll (pframes_t nframes)
107 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
109 int declick = get_transport_declick_required();
110 boost::shared_ptr<RouteList> r = routes.reader ();
113 _click_io->silence (nframes);
116 ltc_tx_send_time_code_for_cycle (_transport_frame, end_frame, _target_transport_speed, _transport_speed, nframes);
118 if (_process_graph) {
119 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
120 _process_graph->routes_no_roll( nframes, _transport_frame, end_frame, non_realtime_work_pending(), declick);
122 PT_TIMING_CHECK (10);
123 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
125 if ((*i)->is_auditioner()) {
129 (*i)->set_pending_declick (declick);
131 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending())) {
132 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
137 PT_TIMING_CHECK (11);
144 /** @param need_butler to be set to true by this method if it needs the butler,
145 * otherwise it must be left alone.
148 Session::process_routes (pframes_t nframes, bool& need_butler)
150 int declick = get_transport_declick_required();
151 boost::shared_ptr<RouteList> r = routes.reader ();
153 if (transport_sub_state & StopPendingCapture) {
154 /* force a declick out */
158 const framepos_t start_frame = _transport_frame;
159 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
161 if (_process_graph) {
162 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
163 _process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);
166 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
170 if ((*i)->is_auditioner()) {
174 (*i)->set_pending_declick (declick);
178 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, b)) < 0) {
192 /** @param need_butler to be set to true by this method if it needs the butler,
193 * otherwise it must be left alone.
196 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
198 boost::shared_ptr<RouteList> r = routes.reader ();
200 const framepos_t start_frame = _transport_frame;
201 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
203 if (_process_graph) {
204 _process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
206 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
210 if ((*i)->is_auditioner()) {
216 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, b)) < 0) {
231 Session::get_track_statistics ()
236 boost::shared_ptr<RouteList> rl = routes.reader();
237 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
239 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
241 if (!tr || tr->hidden()) {
245 pworst = min (pworst, tr->playback_buffer_load());
246 cworst = min (cworst, tr->capture_buffer_load());
249 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
250 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
252 if (actively_recording()) {
257 /** Process callback used when the auditioner is not active */
259 Session::process_with_events (pframes_t nframes)
264 pframes_t this_nframes;
265 framepos_t end_frame;
266 bool session_needs_butler = false;
267 framecnt_t frames_moved;
269 /* make sure the auditioner is silent */
272 auditioner->silence (nframes);
275 /* handle any pending events */
277 while (pending_events.read (&ev, 1) == 1) {
281 /* if we are not in the middle of a state change,
282 and there are immediate events queued up,
286 while (!non_realtime_work_pending() && !immediate_events.empty()) {
287 SessionEvent *ev = immediate_events.front ();
288 immediate_events.pop_front ();
292 /* Decide on what to do with quarter-frame MTC during this cycle */
294 bool const was_sending_qf_mtc = _send_qf_mtc;
295 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
297 if (_transport_speed != 0) {
299 Config->get_send_mtc () &&
300 _transport_speed >= (1 - tolerance) &&
301 _transport_speed <= (1 + tolerance)
304 if (_send_qf_mtc && !was_sending_qf_mtc) {
305 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
306 _send_timecode_update = true;
309 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
310 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
311 a quarter of a second since we sent anything at all, so send a full MTC update
314 _send_timecode_update = true;
317 _pframes_since_last_mtc += nframes;
320 /* Events caused a transport change (or we re-started sending
321 * MTC), so send an MTC Full Frame (Timecode) message. This
322 * is sent whether rolling or not, to give slaves an idea of
323 * ardour time on locates (and allow slow slaves to position
324 * and prepare for rolling)
326 if (_send_timecode_update) {
327 send_full_time_code (_transport_frame, nframes);
330 if (!process_can_proceed()) {
335 if (events.empty() || next_event == events.end()) {
336 process_without_events (nframes);
340 if (_transport_speed == 1.0) {
341 frames_moved = (framecnt_t) nframes;
343 interpolation.set_target_speed (_target_transport_speed);
344 interpolation.set_speed (_transport_speed);
345 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
348 end_frame = _transport_frame + frames_moved;
351 SessionEvent* this_event;
352 Events::iterator the_next_one;
354 if (!process_can_proceed()) {
359 if (!_exporting && _slave) {
360 if (!follow_slave (nframes)) {
365 if (_transport_speed == 0) {
370 if (!_exporting && !timecode_transmission_suspended()) {
371 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
374 framepos_t stop_limit = compute_stop_limit ();
376 if (maybe_stop (stop_limit)) {
381 this_event = *next_event;
382 the_next_one = next_event;
385 /* yes folks, here it is, the actual loop where we really truly
391 this_nframes = nframes; /* real (jack) time relative */
392 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
394 /* running an event, position transport precisely to its time */
395 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
396 /* this isn't quite right for reverse play */
397 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
398 this_nframes = abs (floor(frames_moved / _transport_speed));
403 click (_transport_frame, this_nframes);
405 if (process_routes (this_nframes, session_needs_butler)) {
410 get_track_statistics ();
412 nframes -= this_nframes;
414 if (frames_moved < 0) {
415 decrement_transport_position (-frames_moved);
417 increment_transport_position (frames_moved);
420 maybe_stop (stop_limit);
421 check_declick_out ();
425 _engine.split_cycle (this_nframes);
428 /* now handle this event and all others scheduled for the same time */
430 while (this_event && this_event->action_frame == _transport_frame) {
431 process_event (this_event);
433 if (the_next_one == events.end()) {
436 this_event = *the_next_one;
441 /* if an event left our state changing, do the right thing */
443 if (nframes && non_realtime_work_pending()) {
448 /* this is necessary to handle the case of seamless looping */
449 end_frame = _transport_frame + floor (nframes * _transport_speed);
454 } /* implicit release of route lock */
456 if (session_needs_butler) {
462 Session::reset_slave_state ()
464 average_slave_delta = 1800;
465 delta_accumulator_cnt = 0;
466 have_first_delta_accumulator = false;
467 _slave_state = Stopped;
471 Session::transport_locked () const
475 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
483 Session::follow_slave (pframes_t nframes)
486 framepos_t slave_transport_frame;
487 framecnt_t this_delta;
492 config.set_external_sync (false);
496 _slave->speed_and_position (slave_speed, slave_transport_frame);
498 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
500 if (!_slave->locked()) {
501 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
505 if (slave_transport_frame > _transport_frame) {
506 this_delta = slave_transport_frame - _transport_frame;
509 this_delta = _transport_frame - slave_transport_frame;
513 if (_slave->starting()) {
517 if (_slave->is_always_synced() ||
518 (Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
521 /* if the TC source is synced, then we assume that its
522 speed is binary: 0.0 or 1.0
525 if (slave_speed != 0.0f) {
531 /* if we are chasing and the average delta between us and the
532 master gets too big, we want to switch to silent
533 motion. so keep track of that here.
536 if (_slave_state == Running) {
537 calculate_moving_average_of_slave_delta(dir, this_delta);
541 track_slave_state (slave_speed, slave_transport_frame, this_delta);
543 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
544 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
547 if (_slave_state == Running && !_slave->is_always_synced() &&
548 !(Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
551 if (_transport_speed != 0.0f) {
554 note that average_dir is +1 or -1
559 if (average_slave_delta == 0) {
563 delta = average_slave_delta;
564 delta *= average_dir;
568 if (slave_speed != 0.0) {
569 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
570 (int) (dir * this_delta),
574 slave_transport_frame,
575 average_slave_delta));
579 if (_slave->give_slave_full_control_over_transport_speed()) {
580 set_transport_speed (slave_speed, false, false);
581 //std::cout << "set speed = " << slave_speed << "\n";
583 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
584 request_transport_speed (adjusted_speed);
585 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
586 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
591 if (!actively_recording() && (framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
592 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
600 if (_slave_state == Running && !non_realtime_work_pending()) {
601 /* speed is set, we're locked, and good to go */
606 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
607 follow_slave_silently (nframes, slave_speed);
610 /* don't move at all */
611 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
617 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
619 if (delta_accumulator_cnt >= delta_accumulator_size) {
620 have_first_delta_accumulator = true;
621 delta_accumulator_cnt = 0;
624 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
625 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
628 if (have_first_delta_accumulator) {
629 average_slave_delta = 0L;
630 for (int i = 0; i < delta_accumulator_size; ++i) {
631 average_slave_delta += delta_accumulator[i];
633 average_slave_delta /= (int32_t) delta_accumulator_size;
634 if (average_slave_delta < 0L) {
636 average_slave_delta = abs(average_slave_delta);
644 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t /*this_delta*/)
646 if (slave_speed != 0.0f) {
648 /* slave is running */
650 switch (_slave_state) {
652 if (_slave->requires_seekahead()) {
653 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
654 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
655 /* we can call locate() here because we are in process context */
656 locate (slave_wait_end, false, false);
657 _slave_state = Waiting;
661 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped -> running at %1\n", slave_transport_frame));
663 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
664 average_slave_delta = 0L;
666 Location* al = _locations->auto_loop_location();
668 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
670 request_play_loop(false);
673 if (slave_transport_frame != _transport_frame) {
674 DEBUG_TRACE (DEBUG::Slave, string_compose ("require locate to run. eng: %1 -> sl: %2\n", _transport_frame, slave_transport_frame));
675 locate (slave_transport_frame, false, false);
677 _slave_state = Running;
686 if (_slave_state == Waiting) {
688 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
690 if (slave_transport_frame >= slave_wait_end) {
692 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
694 _slave_state = Running;
696 /* now perform a "micro-seek" within the disk buffers to realign ourselves
697 precisely with the master.
702 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
704 boost::shared_ptr<RouteList> rl = routes.reader();
705 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
706 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
707 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
714 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
715 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
717 tr->internal_playback_seek (frame_delta);
720 _transport_frame += frame_delta;
723 cerr << "cannot micro-seek\n";
729 if (_slave_state == Running && _transport_speed == 0.0f) {
730 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
734 } else { // slave_speed is 0
736 /* slave has stopped */
738 if (_transport_speed != 0.0f) {
739 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
743 if (slave_transport_frame != _transport_frame) {
744 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
745 force_locate (slave_transport_frame, false);
753 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
755 if (slave_speed && _transport_speed) {
757 /* something isn't right, but we should move with the master
763 silent_process_routes (nframes, need_butler);
765 get_track_statistics ();
771 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
773 if (frames_moved < 0) {
774 decrement_transport_position (-frames_moved);
776 increment_transport_position (frames_moved);
779 framepos_t const stop_limit = compute_stop_limit ();
780 maybe_stop (stop_limit);
785 Session::process_without_events (pframes_t nframes)
787 bool session_needs_butler = false;
788 framecnt_t frames_moved;
790 if (!process_can_proceed()) {
795 if (!_exporting && _slave) {
796 if (!follow_slave (nframes)) {
797 ltc_tx_send_time_code_for_cycle (_transport_frame, _transport_frame, 0, 0 , nframes);
802 if (_transport_speed == 0) {
807 if (_transport_speed == 1.0) {
808 frames_moved = (framecnt_t) nframes;
810 interpolation.set_target_speed (_target_transport_speed);
811 interpolation.set_speed (_transport_speed);
812 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
815 if (!_exporting && !timecode_transmission_suspended()) {
816 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
819 ltc_tx_send_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, _target_transport_speed, _transport_speed, nframes);
821 framepos_t const stop_limit = compute_stop_limit ();
823 if (maybe_stop (stop_limit)) {
828 if (maybe_sync_start (nframes)) {
832 click (_transport_frame, nframes);
834 if (process_routes (nframes, session_needs_butler)) {
839 get_track_statistics ();
841 if (frames_moved < 0) {
842 decrement_transport_position (-frames_moved);
844 increment_transport_position (frames_moved);
847 maybe_stop (stop_limit);
848 check_declick_out ();
850 if (session_needs_butler) {
855 /** Process callback used when the auditioner is active.
856 * @param nframes number of frames to process.
859 Session::process_audition (pframes_t nframes)
862 boost::shared_ptr<RouteList> r = routes.reader ();
864 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
865 if (!(*i)->is_auditioner()) {
866 (*i)->silence (nframes);
870 /* run the auditioner, and if it says we need butler service, ask for it */
872 if (auditioner->play_audition (nframes) > 0) {
876 /* if using a monitor section, run it because otherwise we don't hear anything */
878 if (auditioner->needs_monitor()) {
879 _monitor_out->monitor_run (_transport_frame, _transport_frame + nframes, nframes, false);
882 /* handle pending events */
884 while (pending_events.read (&ev, 1) == 1) {
888 /* if we are not in the middle of a state change,
889 and there are immediate events queued up,
893 while (!non_realtime_work_pending() && !immediate_events.empty()) {
894 SessionEvent *ev = immediate_events.front ();
895 immediate_events.pop_front ();
899 if (!auditioner->auditioning()) {
900 /* auditioner no longer active, so go back to the normal process callback */
901 process_function = &Session::process_with_events;
906 Session::maybe_sync_start (pframes_t & nframes)
908 pframes_t sync_offset;
910 if (!waiting_for_sync_offset) {
914 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
916 /* generate silence up to the sync point, then
917 adjust nframes + offset to reflect whatever
921 no_roll (sync_offset);
922 nframes -= sync_offset;
923 Port::increment_global_port_buffer_offset (sync_offset);
924 waiting_for_sync_offset = false;
927 return true; // done, nothing left to process
932 /* sync offset point is not within this process()
933 cycle, so just generate silence. and don't bother
934 with any fancy stuff here, just the minimal silence.
939 if (Config->get_locate_while_waiting_for_sync()) {
940 if (micro_locate (nframes)) {
941 /* XXX ERROR !!! XXX */
945 return true; // done, nothing left to process
952 Session::queue_event (SessionEvent* ev)
954 if (_state_of_the_state & Deletion) {
956 } else if (_state_of_the_state & Loading) {
959 pending_events.write (&ev, 1);
964 Session::set_next_event ()
966 if (events.empty()) {
967 next_event = events.end();
971 if (next_event == events.end()) {
972 next_event = events.begin();
975 if ((*next_event)->action_frame > _transport_frame) {
976 next_event = events.begin();
979 for (; next_event != events.end(); ++next_event) {
980 if ((*next_event)->action_frame >= _transport_frame) {
987 Session::process_event (SessionEvent* ev)
992 /* if we're in the middle of a state change (i.e. waiting
993 for the butler thread to complete the non-realtime
994 part of the change), we'll just have to queue this
995 event for a time when the change is complete.
998 if (non_realtime_work_pending()) {
1000 /* except locates, which we have the capability to handle */
1002 if (ev->type != SessionEvent::Locate) {
1003 immediate_events.insert (immediate_events.end(), ev);
1009 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1012 case SessionEvent::SetLoop:
1013 set_play_loop (ev->yes_or_no);
1016 case SessionEvent::AutoLoop:
1018 /* roll after locate, do not flush, set "with loop"
1019 true only if we are seamless looping
1021 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1027 case SessionEvent::AutoLoopDeclick:
1029 /* Request a declick fade-out and a fade-in; the fade-out will happen
1030 at the end of the loop, and the fade-in at the start.
1032 transport_sub_state |= (PendingLoopDeclickOut | PendingLoopDeclickIn);
1038 case SessionEvent::Locate:
1039 if (ev->yes_or_no) {
1040 /* args: do not roll after locate, do flush, not with loop */
1041 locate (ev->target_frame, false, true, false);
1043 /* args: do not roll after locate, do flush, not with loop */
1044 start_locate (ev->target_frame, false, true, false);
1046 _send_timecode_update = true;
1049 case SessionEvent::LocateRoll:
1050 if (ev->yes_or_no) {
1051 /* args: roll after locate, do flush, not with loop */
1052 locate (ev->target_frame, true, true, false);
1054 /* args: roll after locate, do flush, not with loop */
1055 start_locate (ev->target_frame, true, true, false);
1057 _send_timecode_update = true;
1060 case SessionEvent::LocateRollLocate:
1061 // locate is handled by ::request_roll_at_and_return()
1062 _requested_return_frame = ev->target_frame;
1063 request_locate (ev->target2_frame, true);
1067 case SessionEvent::SetTransportSpeed:
1068 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no, ev->third_yes_or_no);
1071 case SessionEvent::PunchIn:
1072 // cerr << "PunchIN at " << transport_frame() << endl;
1073 if (config.get_punch_in() && record_status() == Enabled) {
1080 case SessionEvent::PunchOut:
1081 // cerr << "PunchOUT at " << transport_frame() << endl;
1082 if (config.get_punch_out()) {
1083 step_back_from_record ();
1089 case SessionEvent::StopOnce:
1090 if (!non_realtime_work_pending()) {
1091 stop_transport (ev->yes_or_no);
1092 _clear_event_type (SessionEvent::StopOnce);
1098 case SessionEvent::RangeStop:
1099 if (!non_realtime_work_pending()) {
1100 stop_transport (ev->yes_or_no);
1106 case SessionEvent::RangeLocate:
1107 /* args: roll after locate, do flush, not with loop */
1108 start_locate (ev->target_frame, true, true, false);
1113 case SessionEvent::Overwrite:
1114 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1117 case SessionEvent::SetTrackSpeed:
1118 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1121 case SessionEvent::SetSyncSource:
1122 DEBUG_TRACE (DEBUG::Slave, "seen request for new slave\n");
1123 use_sync_source (ev->slave);
1126 case SessionEvent::Audition:
1127 set_audition (ev->region);
1128 // drop reference to region
1129 ev->region.reset ();
1132 case SessionEvent::InputConfigurationChange:
1133 add_post_transport_work (PostTransportInputChange);
1134 _butler->schedule_transport_work ();
1137 case SessionEvent::SetPlayAudioRange:
1138 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1141 case SessionEvent::RealTimeOperation:
1143 del = false; // other side of RT request needs to clean up
1146 case SessionEvent::AdjustPlaybackBuffering:
1147 schedule_playback_buffering_adjustment ();
1150 case SessionEvent::AdjustCaptureBuffering:
1151 schedule_capture_buffering_adjustment ();
1154 case SessionEvent::SetTimecodeTransmission:
1155 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1159 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1165 del = del && !_remove_event (ev);
1174 Session::compute_stop_limit () const
1176 if (!Config->get_stop_at_session_end ()) {
1177 return max_framepos;
1181 return max_framepos;
1185 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1186 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1188 if (actively_recording ()) {
1189 /* permanently recording */
1190 return max_framepos;
1191 } else if (punching_in && !punching_out) {
1192 /* punching in but never out */
1193 return max_framepos;
1194 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_frame()) {
1195 /* punching in and punching out after session end */
1196 return max_framepos;
1199 return current_end_frame ();