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/thread.h>
30 #include "ardour/ardour.h"
31 #include "ardour/audioengine.h"
32 #include "ardour/auditioner.h"
33 #include "ardour/butler.h"
34 #include "ardour/debug.h"
35 #include "ardour/process_thread.h"
36 #include "ardour/session.h"
37 #include "ardour/slave.h"
38 #include "ardour/timestamps.h"
39 #include "ardour/graph.h"
40 #include "ardour/audio_port.h"
41 #include "ardour/tempo.h"
42 #include "ardour/ticker.h"
43 #include "ardour/cycle_timer.h"
45 #include "midi++/manager.h"
46 #include "midi++/mmc.h"
50 #include <xmmintrin.h>
52 using namespace ARDOUR;
56 /** Called by the audio engine when there is work to be done with JACK.
57 * @param nframes Number of frames to process.
61 Session::process (pframes_t nframes)
63 framepos_t transport_at_start = _transport_frame;
67 if (processing_blocked()) {
72 if (non_realtime_work_pending()) {
73 if (!_butler->transport_work_requested ()) {
78 _engine.main_thread()->get_buffers ();
80 (this->*process_function) (nframes);
82 _engine.main_thread()->drop_buffers ();
84 /* deliver MIDI clock. Note that we need to use the transport frame
85 * position at the start of process(), not the value at the end of
86 * it. We may already have ticked() because of a transport state
87 * change, for example.
91 if (!_engine.freewheeling() && Config->get_send_midi_clock() && transport_speed() == 1.0f && midi_clock->has_midi_port()) {
92 midi_clock->tick (transport_at_start);
95 /* don't bother with a message */
98 SendFeedback (); /* EMIT SIGNAL */
102 Session::fail_roll (pframes_t nframes)
104 return no_roll (nframes);
108 Session::no_roll (pframes_t nframes)
112 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
114 bool declick = get_transport_declick_required();
115 boost::shared_ptr<RouteList> r = routes.reader ();
118 _click_io->silence (nframes);
121 if (_process_graph) {
122 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
123 _process_graph->routes_no_roll( nframes, _transport_frame, end_frame, non_realtime_work_pending(), declick);
125 PT_TIMING_CHECK (10);
126 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
128 if ((*i)->is_hidden()) {
132 (*i)->set_pending_declick (declick);
134 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending())) {
135 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
140 PT_TIMING_CHECK (11);
147 /** @param need_butler to be set to true by this method if it needs the butler,
148 * otherwise it must be left alone.
151 Session::process_routes (pframes_t nframes, bool& need_butler)
153 int declick = get_transport_declick_required();
154 boost::shared_ptr<RouteList> r = routes.reader ();
156 if (transport_sub_state & StopPendingCapture) {
157 /* force a declick out */
161 const framepos_t start_frame = _transport_frame;
162 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
164 if (_process_graph) {
165 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
166 _process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);
169 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
173 if ((*i)->is_hidden()) {
177 (*i)->set_pending_declick (declick);
181 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, b)) < 0) {
195 /** @param need_butler to be set to true by this method if it needs the butler,
196 * otherwise it must be left alone.
199 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
201 boost::shared_ptr<RouteList> r = routes.reader ();
203 const framepos_t start_frame = _transport_frame;
204 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
206 if (_process_graph) {
207 _process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
209 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
213 if ((*i)->is_hidden()) {
219 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, b)) < 0) {
234 Session::get_track_statistics ()
239 boost::shared_ptr<RouteList> rl = routes.reader();
240 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
242 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
244 if (!tr || tr->hidden()) {
248 pworst = min (pworst, tr->playback_buffer_load());
249 cworst = min (cworst, tr->capture_buffer_load());
252 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
253 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
255 if (actively_recording()) {
260 /** Process callback used when the auditioner is not active */
262 Session::process_with_events (pframes_t nframes)
267 pframes_t this_nframes;
268 framepos_t end_frame;
269 bool session_needs_butler = false;
270 framecnt_t frames_moved;
272 /* make sure the auditioner is silent */
275 auditioner->silence (nframes);
278 /* handle any pending events */
280 while (pending_events.read (&ev, 1) == 1) {
284 /* if we are not in the middle of a state change,
285 and there are immediate events queued up,
289 while (!non_realtime_work_pending() && !immediate_events.empty()) {
290 SessionEvent *ev = immediate_events.front ();
291 immediate_events.pop_front ();
295 /* Decide on what to do with quarter-frame MTC during this cycle */
297 bool const was_sending_qf_mtc = _send_qf_mtc;
298 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
300 if (_transport_speed != 0) {
302 Config->get_send_mtc () &&
303 _transport_speed >= (1 - tolerance) &&
304 _transport_speed <= (1 + tolerance)
307 if (_send_qf_mtc && !was_sending_qf_mtc) {
308 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
309 _send_timecode_update = true;
312 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
313 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
314 a quarter of a second since we sent anything at all, so send a full MTC update
317 _send_timecode_update = true;
320 _pframes_since_last_mtc += nframes;
323 /* Events caused a transport change (or we re-started sending
324 * MTC), so send an MTC Full Frame (Timecode) message. This
325 * is sent whether rolling or not, to give slaves an idea of
326 * ardour time on locates (and allow slow slaves to position
327 * and prepare for rolling)
329 if (_send_timecode_update) {
330 send_full_time_code (_transport_frame);
333 if (!process_can_proceed()) {
338 if (events.empty() || next_event == events.end()) {
339 process_without_events (nframes);
343 if (_transport_speed == 1.0) {
344 frames_moved = (framecnt_t) nframes;
346 interpolation.set_target_speed (fabs(_target_transport_speed));
347 interpolation.set_speed (fabs(_transport_speed));
348 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
351 end_frame = _transport_frame + frames_moved;
354 SessionEvent* this_event;
355 Events::iterator the_next_one;
357 if (!process_can_proceed()) {
362 if (!_exporting && _slave) {
363 if (!follow_slave (nframes)) {
368 if (_transport_speed == 0) {
373 if (!_exporting && !timecode_transmission_suspended()) {
374 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
377 framepos_t stop_limit = compute_stop_limit ();
379 if (maybe_stop (stop_limit)) {
384 this_event = *next_event;
385 the_next_one = next_event;
388 /* yes folks, here it is, the actual loop where we really truly
394 this_nframes = nframes; /* real (jack) time relative */
395 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
397 /* running an event, position transport precisely to its time */
398 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
399 /* this isn't quite right for reverse play */
400 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
401 this_nframes = abs (floor(frames_moved / _transport_speed));
406 click (_transport_frame, this_nframes);
408 if (process_routes (this_nframes, session_needs_butler)) {
413 get_track_statistics ();
415 nframes -= this_nframes;
417 if (frames_moved < 0) {
418 decrement_transport_position (-frames_moved);
420 increment_transport_position (frames_moved);
423 maybe_stop (stop_limit);
424 check_declick_out ();
427 _engine.split_cycle (this_nframes);
429 /* now handle this event and all others scheduled for the same time */
431 while (this_event && this_event->action_frame == _transport_frame) {
432 process_event (this_event);
434 if (the_next_one == events.end()) {
437 this_event = *the_next_one;
442 /* if an event left our state changing, do the right thing */
444 if (nframes && non_realtime_work_pending()) {
449 /* this is necessary to handle the case of seamless looping */
450 end_frame = _transport_frame + floor (nframes * _transport_speed);
455 } /* implicit release of route lock */
457 if (session_needs_butler) {
463 Session::reset_slave_state ()
465 average_slave_delta = 1800;
466 delta_accumulator_cnt = 0;
467 have_first_delta_accumulator = false;
468 _slave_state = Stopped;
472 Session::transport_locked () const
476 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
484 Session::follow_slave (pframes_t nframes)
487 framepos_t slave_transport_frame;
488 framecnt_t this_delta;
493 config.set_external_sync (false);
497 _slave->speed_and_position (slave_speed, slave_transport_frame);
499 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
501 if (!_slave->locked()) {
502 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
506 if (slave_transport_frame > _transport_frame) {
507 this_delta = slave_transport_frame - _transport_frame;
510 this_delta = _transport_frame - slave_transport_frame;
514 if (_slave->starting()) {
518 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
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() && !config.get_timecode_source_is_synced()) {
548 if (_transport_speed != 0.0f) {
551 note that average_dir is +1 or -1
556 if (average_slave_delta == 0) {
560 delta = average_slave_delta;
561 delta *= average_dir;
565 if (slave_speed != 0.0) {
566 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
567 (int) (dir * this_delta),
571 slave_transport_frame,
572 average_slave_delta));
576 if (_slave->give_slave_full_control_over_transport_speed()) {
577 set_transport_speed (slave_speed, false, false);
578 //std::cout << "set speed = " << slave_speed << "\n";
580 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
581 request_transport_speed (adjusted_speed);
582 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
583 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
588 if ((framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
589 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
597 if (_slave_state == Running && !non_realtime_work_pending()) {
598 /* speed is set, we're locked, and good to go */
603 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
604 follow_slave_silently (nframes, slave_speed);
607 /* don't move at all */
608 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
614 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
616 if (delta_accumulator_cnt >= delta_accumulator_size) {
617 have_first_delta_accumulator = true;
618 delta_accumulator_cnt = 0;
621 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
622 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
625 if (have_first_delta_accumulator) {
626 average_slave_delta = 0L;
627 for (int i = 0; i < delta_accumulator_size; ++i) {
628 average_slave_delta += delta_accumulator[i];
630 average_slave_delta /= (int32_t) delta_accumulator_size;
631 if (average_slave_delta < 0L) {
633 average_slave_delta = abs(average_slave_delta);
641 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t /*this_delta*/)
643 if (slave_speed != 0.0f) {
645 /* slave is running */
647 switch (_slave_state) {
649 if (_slave->requires_seekahead()) {
650 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
651 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
652 /* we can call locate() here because we are in process context */
653 locate (slave_wait_end, false, false);
654 _slave_state = Waiting;
658 _slave_state = Running;
660 Location* al = _locations->auto_loop_location();
662 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
664 request_play_loop(false);
667 if (slave_transport_frame != _transport_frame) {
668 locate (slave_transport_frame, false, false);
678 if (_slave_state == Waiting) {
680 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
682 if (slave_transport_frame >= slave_wait_end) {
684 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
686 _slave_state = Running;
688 /* now perform a "micro-seek" within the disk buffers to realign ourselves
689 precisely with the master.
694 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
696 boost::shared_ptr<RouteList> rl = routes.reader();
697 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
698 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
699 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
706 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
707 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
709 tr->internal_playback_seek (frame_delta);
712 _transport_frame += frame_delta;
715 cerr << "cannot micro-seek\n";
719 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
720 average_slave_delta = 0L;
724 if (_slave_state == Running && _transport_speed == 0.0f) {
725 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
729 } else { // slave_speed is 0
731 /* slave has stopped */
733 if (_transport_speed != 0.0f) {
734 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
738 if (slave_transport_frame != _transport_frame) {
739 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
740 force_locate (slave_transport_frame, false);
743 _slave_state = Stopped;
748 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
750 if (slave_speed && _transport_speed) {
752 /* something isn't right, but we should move with the master
758 silent_process_routes (nframes, need_butler);
760 get_track_statistics ();
766 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
768 if (frames_moved < 0) {
769 decrement_transport_position (-frames_moved);
771 increment_transport_position (frames_moved);
774 framepos_t const stop_limit = compute_stop_limit ();
775 maybe_stop (stop_limit);
780 Session::process_without_events (pframes_t nframes)
782 bool session_needs_butler = false;
783 framecnt_t frames_moved;
785 if (!process_can_proceed()) {
790 if (!_exporting && _slave) {
791 if (!follow_slave (nframes)) {
796 if (_transport_speed == 0) {
801 if (_transport_speed == 1.0) {
802 frames_moved = (framecnt_t) nframes;
804 interpolation.set_target_speed (fabs(_target_transport_speed));
805 interpolation.set_speed (fabs(_transport_speed));
806 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
809 if (!_exporting && !timecode_transmission_suspended()) {
810 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
813 framepos_t const stop_limit = compute_stop_limit ();
815 if (maybe_stop (stop_limit)) {
820 if (maybe_sync_start (nframes)) {
824 click (_transport_frame, nframes);
826 if (process_routes (nframes, session_needs_butler)) {
831 get_track_statistics ();
833 /* XXX: I'm not sure whether this is correct, but at least it
834 matches process_with_events, so that this new frames_moved
835 is -ve when transport speed is -ve. This means that the
836 transport position is updated correctly when we are in
837 reverse. It seems a bit wrong that we're not using the
838 interpolator to compute this.
841 frames_moved = (framecnt_t) floor (_transport_speed * nframes);
843 if (frames_moved < 0) {
844 decrement_transport_position (-frames_moved);
846 increment_transport_position (frames_moved);
849 maybe_stop (stop_limit);
850 check_declick_out ();
852 if (session_needs_butler) {
857 /** Process callback used when the auditioner is active.
858 * @param nframes number of frames to process.
861 Session::process_audition (pframes_t nframes)
864 boost::shared_ptr<RouteList> r = routes.reader ();
866 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
867 if (!(*i)->is_hidden()) {
868 (*i)->silence (nframes);
872 /* run the auditioner, and if it says we need butler service, ask for it */
874 if (auditioner->play_audition (nframes) > 0) {
878 /* if using a monitor section, run it because otherwise we don't hear anything */
880 if (auditioner->needs_monitor()) {
881 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
884 /* handle pending events */
886 while (pending_events.read (&ev, 1) == 1) {
890 /* if we are not in the middle of a state change,
891 and there are immediate events queued up,
895 while (!non_realtime_work_pending() && !immediate_events.empty()) {
896 SessionEvent *ev = immediate_events.front ();
897 immediate_events.pop_front ();
901 if (!auditioner->auditioning()) {
902 /* auditioner no longer active, so go back to the normal process callback */
903 process_function = &Session::process_with_events;
908 Session::maybe_sync_start (pframes_t & nframes)
910 pframes_t sync_offset;
912 if (!waiting_for_sync_offset) {
916 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
918 /* generate silence up to the sync point, then
919 adjust nframes + offset to reflect whatever
923 no_roll (sync_offset);
924 nframes -= sync_offset;
925 Port::increment_global_port_buffer_offset (sync_offset);
926 waiting_for_sync_offset = false;
929 return true; // done, nothing left to process
934 /* sync offset point is not within this process()
935 cycle, so just generate silence. and don't bother
936 with any fancy stuff here, just the minimal silence.
941 if (Config->get_locate_while_waiting_for_sync()) {
942 if (micro_locate (nframes)) {
943 /* XXX ERROR !!! XXX */
947 return true; // done, nothing left to process
954 Session::queue_event (SessionEvent* ev)
956 if (_state_of_the_state & Deletion) {
958 } else if (_state_of_the_state & Loading) {
961 pending_events.write (&ev, 1);
966 Session::set_next_event ()
968 if (events.empty()) {
969 next_event = events.end();
973 if (next_event == events.end()) {
974 next_event = events.begin();
977 if ((*next_event)->action_frame > _transport_frame) {
978 next_event = events.begin();
981 for (; next_event != events.end(); ++next_event) {
982 if ((*next_event)->action_frame >= _transport_frame) {
989 Session::process_event (SessionEvent* ev)
994 /* if we're in the middle of a state change (i.e. waiting
995 for the butler thread to complete the non-realtime
996 part of the change), we'll just have to queue this
997 event for a time when the change is complete.
1000 if (non_realtime_work_pending()) {
1002 /* except locates, which we have the capability to handle */
1004 if (ev->type != SessionEvent::Locate) {
1005 immediate_events.insert (immediate_events.end(), ev);
1011 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1014 case SessionEvent::SetLoop:
1015 set_play_loop (ev->yes_or_no);
1018 case SessionEvent::AutoLoop:
1020 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1026 case SessionEvent::Locate:
1027 if (ev->yes_or_no) {
1028 // cerr << "forced locate to " << ev->target_frame << endl;
1029 locate (ev->target_frame, false, true, false);
1031 // cerr << "soft locate to " << ev->target_frame << endl;
1032 start_locate (ev->target_frame, false, true, false);
1034 _send_timecode_update = true;
1037 case SessionEvent::LocateRoll:
1038 if (ev->yes_or_no) {
1039 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1040 locate (ev->target_frame, true, true, false);
1042 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1043 start_locate (ev->target_frame, true, true, false);
1045 _send_timecode_update = true;
1048 case SessionEvent::LocateRollLocate:
1049 // locate is handled by ::request_roll_at_and_return()
1050 _requested_return_frame = ev->target_frame;
1051 request_locate (ev->target2_frame, true);
1055 case SessionEvent::SetTransportSpeed:
1056 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1059 case SessionEvent::PunchIn:
1060 // cerr << "PunchIN at " << transport_frame() << endl;
1061 if (config.get_punch_in() && record_status() == Enabled) {
1068 case SessionEvent::PunchOut:
1069 // cerr << "PunchOUT at " << transport_frame() << endl;
1070 if (config.get_punch_out()) {
1071 step_back_from_record ();
1077 case SessionEvent::StopOnce:
1078 if (!non_realtime_work_pending()) {
1079 stop_transport (ev->yes_or_no);
1080 _clear_event_type (SessionEvent::StopOnce);
1086 case SessionEvent::RangeStop:
1087 if (!non_realtime_work_pending()) {
1088 stop_transport (ev->yes_or_no);
1094 case SessionEvent::RangeLocate:
1095 start_locate (ev->target_frame, true, true, false);
1100 case SessionEvent::Overwrite:
1101 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1104 case SessionEvent::SetTrackSpeed:
1105 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1108 case SessionEvent::SetSyncSource:
1109 use_sync_source (ev->slave);
1112 case SessionEvent::Audition:
1113 set_audition (ev->region);
1114 // drop reference to region
1115 ev->region.reset ();
1118 case SessionEvent::InputConfigurationChange:
1119 add_post_transport_work (PostTransportInputChange);
1120 _butler->schedule_transport_work ();
1123 case SessionEvent::SetPlayAudioRange:
1124 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1127 case SessionEvent::RealTimeOperation:
1129 del = false; // other side of RT request needs to clean up
1132 case SessionEvent::AdjustPlaybackBuffering:
1133 schedule_playback_buffering_adjustment ();
1136 case SessionEvent::AdjustCaptureBuffering:
1137 schedule_capture_buffering_adjustment ();
1140 case SessionEvent::SetTimecodeTransmission:
1141 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1145 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1151 del = del && !_remove_event (ev);
1160 Session::compute_stop_limit () const
1162 if (!Config->get_stop_at_session_end ()) {
1163 return max_framepos;
1166 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1167 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1169 if (actively_recording ()) {
1170 /* permanently recording */
1171 return max_framepos;
1172 } else if (punching_in && !punching_out) {
1173 /* punching in but never out */
1174 return max_framepos;
1175 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_frame()) {
1176 /* punching in and punching out after session end */
1177 return max_framepos;
1180 return current_end_frame ();