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 ();
424 _engine.split_cycle (this_nframes);
426 /* now handle this event and all others scheduled for the same time */
428 while (this_event && this_event->action_frame == _transport_frame) {
429 process_event (this_event);
431 if (the_next_one == events.end()) {
434 this_event = *the_next_one;
439 /* if an event left our state changing, do the right thing */
441 if (nframes && non_realtime_work_pending()) {
446 /* this is necessary to handle the case of seamless looping */
447 end_frame = _transport_frame + floor (nframes * _transport_speed);
452 } /* implicit release of route lock */
454 if (session_needs_butler) {
460 Session::reset_slave_state ()
462 average_slave_delta = 1800;
463 delta_accumulator_cnt = 0;
464 have_first_delta_accumulator = false;
465 _slave_state = Stopped;
469 Session::transport_locked () const
473 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
481 Session::follow_slave (pframes_t nframes)
484 framepos_t slave_transport_frame;
485 framecnt_t this_delta;
490 config.set_external_sync (false);
494 _slave->speed_and_position (slave_speed, slave_transport_frame);
496 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
498 if (!_slave->locked()) {
499 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
503 if (slave_transport_frame > _transport_frame) {
504 this_delta = slave_transport_frame - _transport_frame;
507 this_delta = _transport_frame - slave_transport_frame;
511 if (_slave->starting()) {
515 if (_slave->is_always_synced() ||
516 (Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
519 /* if the TC source is synced, then we assume that its
520 speed is binary: 0.0 or 1.0
523 if (slave_speed != 0.0f) {
529 /* if we are chasing and the average delta between us and the
530 master gets too big, we want to switch to silent
531 motion. so keep track of that here.
534 if (_slave_state == Running) {
535 calculate_moving_average_of_slave_delta(dir, this_delta);
539 track_slave_state (slave_speed, slave_transport_frame, this_delta);
541 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
542 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
545 if (_slave_state == Running && !_slave->is_always_synced() &&
546 !(Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
549 if (_transport_speed != 0.0f) {
552 note that average_dir is +1 or -1
557 if (average_slave_delta == 0) {
561 delta = average_slave_delta;
562 delta *= average_dir;
566 if (slave_speed != 0.0) {
567 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
568 (int) (dir * this_delta),
572 slave_transport_frame,
573 average_slave_delta));
577 if (_slave->give_slave_full_control_over_transport_speed()) {
578 set_transport_speed (slave_speed, false, false);
579 //std::cout << "set speed = " << slave_speed << "\n";
581 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
582 request_transport_speed (adjusted_speed);
583 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
584 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
589 if (!actively_recording() && (framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
590 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
598 if (_slave_state == Running && !non_realtime_work_pending()) {
599 /* speed is set, we're locked, and good to go */
604 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
605 follow_slave_silently (nframes, slave_speed);
608 /* don't move at all */
609 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
615 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
617 if (delta_accumulator_cnt >= delta_accumulator_size) {
618 have_first_delta_accumulator = true;
619 delta_accumulator_cnt = 0;
622 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
623 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
626 if (have_first_delta_accumulator) {
627 average_slave_delta = 0L;
628 for (int i = 0; i < delta_accumulator_size; ++i) {
629 average_slave_delta += delta_accumulator[i];
631 average_slave_delta /= (int32_t) delta_accumulator_size;
632 if (average_slave_delta < 0L) {
634 average_slave_delta = abs(average_slave_delta);
642 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t /*this_delta*/)
644 if (slave_speed != 0.0f) {
646 /* slave is running */
648 switch (_slave_state) {
650 if (_slave->requires_seekahead()) {
651 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
652 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
653 /* we can call locate() here because we are in process context */
654 locate (slave_wait_end, false, false);
655 _slave_state = Waiting;
659 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped -> running at %1\n", slave_transport_frame));
661 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
662 average_slave_delta = 0L;
664 Location* al = _locations->auto_loop_location();
666 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
668 request_play_loop(false);
671 if (slave_transport_frame != _transport_frame) {
672 DEBUG_TRACE (DEBUG::Slave, string_compose ("require locate to run. eng: %1 -> sl: %2\n", _transport_frame, slave_transport_frame));
673 locate (slave_transport_frame, false, false);
675 _slave_state = Running;
684 if (_slave_state == Waiting) {
686 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
688 if (slave_transport_frame >= slave_wait_end) {
690 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
692 _slave_state = Running;
694 /* now perform a "micro-seek" within the disk buffers to realign ourselves
695 precisely with the master.
700 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
702 boost::shared_ptr<RouteList> rl = routes.reader();
703 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
704 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
705 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
712 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
713 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
715 tr->internal_playback_seek (frame_delta);
718 _transport_frame += frame_delta;
721 cerr << "cannot micro-seek\n";
727 if (_slave_state == Running && _transport_speed == 0.0f) {
728 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
732 } else { // slave_speed is 0
734 /* slave has stopped */
736 if (_transport_speed != 0.0f) {
737 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
741 if (slave_transport_frame != _transport_frame) {
742 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
743 force_locate (slave_transport_frame, false);
751 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
753 if (slave_speed && _transport_speed) {
755 /* something isn't right, but we should move with the master
761 silent_process_routes (nframes, need_butler);
763 get_track_statistics ();
769 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
771 if (frames_moved < 0) {
772 decrement_transport_position (-frames_moved);
774 increment_transport_position (frames_moved);
777 framepos_t const stop_limit = compute_stop_limit ();
778 maybe_stop (stop_limit);
783 Session::process_without_events (pframes_t nframes)
785 bool session_needs_butler = false;
786 framecnt_t frames_moved;
788 if (!process_can_proceed()) {
793 if (!_exporting && _slave) {
794 if (!follow_slave (nframes)) {
795 ltc_tx_send_time_code_for_cycle (_transport_frame, _transport_frame, 0, 0 , nframes);
800 if (_transport_speed == 0) {
805 if (_transport_speed == 1.0) {
806 frames_moved = (framecnt_t) nframes;
808 interpolation.set_target_speed (_target_transport_speed);
809 interpolation.set_speed (_transport_speed);
810 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
813 if (!_exporting && !timecode_transmission_suspended()) {
814 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
817 ltc_tx_send_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, _target_transport_speed, _transport_speed, nframes);
819 framepos_t const stop_limit = compute_stop_limit ();
821 if (maybe_stop (stop_limit)) {
826 if (maybe_sync_start (nframes)) {
830 click (_transport_frame, nframes);
832 if (process_routes (nframes, session_needs_butler)) {
837 get_track_statistics ();
839 if (frames_moved < 0) {
840 decrement_transport_position (-frames_moved);
842 increment_transport_position (frames_moved);
845 maybe_stop (stop_limit);
846 check_declick_out ();
848 if (session_needs_butler) {
853 /** Process callback used when the auditioner is active.
854 * @param nframes number of frames to process.
857 Session::process_audition (pframes_t nframes)
860 boost::shared_ptr<RouteList> r = routes.reader ();
862 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
863 if (!(*i)->is_auditioner()) {
864 (*i)->silence (nframes);
868 /* run the auditioner, and if it says we need butler service, ask for it */
870 if (auditioner->play_audition (nframes) > 0) {
874 /* if using a monitor section, run it because otherwise we don't hear anything */
876 if (auditioner->needs_monitor()) {
877 _monitor_out->monitor_run (_transport_frame, _transport_frame + nframes, nframes, false);
880 /* handle pending events */
882 while (pending_events.read (&ev, 1) == 1) {
886 /* if we are not in the middle of a state change,
887 and there are immediate events queued up,
891 while (!non_realtime_work_pending() && !immediate_events.empty()) {
892 SessionEvent *ev = immediate_events.front ();
893 immediate_events.pop_front ();
897 if (!auditioner->auditioning()) {
898 /* auditioner no longer active, so go back to the normal process callback */
899 process_function = &Session::process_with_events;
904 Session::maybe_sync_start (pframes_t & nframes)
906 pframes_t sync_offset;
908 if (!waiting_for_sync_offset) {
912 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
914 /* generate silence up to the sync point, then
915 adjust nframes + offset to reflect whatever
919 no_roll (sync_offset);
920 nframes -= sync_offset;
921 Port::increment_global_port_buffer_offset (sync_offset);
922 waiting_for_sync_offset = false;
925 return true; // done, nothing left to process
930 /* sync offset point is not within this process()
931 cycle, so just generate silence. and don't bother
932 with any fancy stuff here, just the minimal silence.
937 if (Config->get_locate_while_waiting_for_sync()) {
938 if (micro_locate (nframes)) {
939 /* XXX ERROR !!! XXX */
943 return true; // done, nothing left to process
950 Session::queue_event (SessionEvent* ev)
952 if (_state_of_the_state & Deletion) {
954 } else if (_state_of_the_state & Loading) {
957 pending_events.write (&ev, 1);
962 Session::set_next_event ()
964 if (events.empty()) {
965 next_event = events.end();
969 if (next_event == events.end()) {
970 next_event = events.begin();
973 if ((*next_event)->action_frame > _transport_frame) {
974 next_event = events.begin();
977 for (; next_event != events.end(); ++next_event) {
978 if ((*next_event)->action_frame >= _transport_frame) {
985 Session::process_event (SessionEvent* ev)
990 /* if we're in the middle of a state change (i.e. waiting
991 for the butler thread to complete the non-realtime
992 part of the change), we'll just have to queue this
993 event for a time when the change is complete.
996 if (non_realtime_work_pending()) {
998 /* except locates, which we have the capability to handle */
1000 if (ev->type != SessionEvent::Locate) {
1001 immediate_events.insert (immediate_events.end(), ev);
1007 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1010 case SessionEvent::SetLoop:
1011 set_play_loop (ev->yes_or_no);
1014 case SessionEvent::AutoLoop:
1016 /* roll after locate, do not flush, set "with loop"
1017 true only if we are seamless looping
1019 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1025 case SessionEvent::AutoLoopDeclick:
1027 /* Request a declick fade-out and a fade-in; the fade-out will happen
1028 at the end of the loop, and the fade-in at the start.
1030 transport_sub_state |= (PendingLoopDeclickOut | PendingLoopDeclickIn);
1036 case SessionEvent::Locate:
1037 if (ev->yes_or_no) {
1038 /* args: do not roll after locate, do flush, not with loop */
1039 locate (ev->target_frame, false, true, false);
1041 /* args: do not roll after locate, do flush, not with loop */
1042 start_locate (ev->target_frame, false, true, false);
1044 _send_timecode_update = true;
1047 case SessionEvent::LocateRoll:
1048 if (ev->yes_or_no) {
1049 /* args: roll after locate, do flush, not with loop */
1050 locate (ev->target_frame, true, true, false);
1052 /* args: roll after locate, do flush, not with loop */
1053 start_locate (ev->target_frame, true, true, false);
1055 _send_timecode_update = true;
1058 case SessionEvent::LocateRollLocate:
1059 // locate is handled by ::request_roll_at_and_return()
1060 _requested_return_frame = ev->target_frame;
1061 request_locate (ev->target2_frame, true);
1065 case SessionEvent::SetTransportSpeed:
1066 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no, ev->third_yes_or_no);
1069 case SessionEvent::PunchIn:
1070 // cerr << "PunchIN at " << transport_frame() << endl;
1071 if (config.get_punch_in() && record_status() == Enabled) {
1078 case SessionEvent::PunchOut:
1079 // cerr << "PunchOUT at " << transport_frame() << endl;
1080 if (config.get_punch_out()) {
1081 step_back_from_record ();
1087 case SessionEvent::StopOnce:
1088 if (!non_realtime_work_pending()) {
1089 stop_transport (ev->yes_or_no);
1090 _clear_event_type (SessionEvent::StopOnce);
1096 case SessionEvent::RangeStop:
1097 if (!non_realtime_work_pending()) {
1098 stop_transport (ev->yes_or_no);
1104 case SessionEvent::RangeLocate:
1105 /* args: roll after locate, do flush, not with loop */
1106 start_locate (ev->target_frame, true, true, false);
1111 case SessionEvent::Overwrite:
1112 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1115 case SessionEvent::SetTrackSpeed:
1116 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1119 case SessionEvent::SetSyncSource:
1120 DEBUG_TRACE (DEBUG::Slave, "seen request for new slave\n");
1121 use_sync_source (ev->slave);
1124 case SessionEvent::Audition:
1125 set_audition (ev->region);
1126 // drop reference to region
1127 ev->region.reset ();
1130 case SessionEvent::InputConfigurationChange:
1131 add_post_transport_work (PostTransportInputChange);
1132 _butler->schedule_transport_work ();
1135 case SessionEvent::SetPlayAudioRange:
1136 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1139 case SessionEvent::RealTimeOperation:
1141 del = false; // other side of RT request needs to clean up
1144 case SessionEvent::AdjustPlaybackBuffering:
1145 schedule_playback_buffering_adjustment ();
1148 case SessionEvent::AdjustCaptureBuffering:
1149 schedule_capture_buffering_adjustment ();
1152 case SessionEvent::SetTimecodeTransmission:
1153 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1157 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1163 del = del && !_remove_event (ev);
1172 Session::compute_stop_limit () const
1174 if (!Config->get_stop_at_session_end ()) {
1175 return max_framepos;
1179 return max_framepos;
1183 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1184 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1186 if (actively_recording ()) {
1187 /* permanently recording */
1188 return max_framepos;
1189 } else if (punching_in && !punching_out) {
1190 /* punching in but never out */
1191 return max_framepos;
1192 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_frame()) {
1193 /* punching in and punching out after session end */
1194 return max_framepos;
1197 return current_end_frame ();