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 */
103 Session::fail_roll (pframes_t nframes)
105 return no_roll (nframes);
109 Session::no_roll (pframes_t nframes)
113 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
115 bool declick = get_transport_declick_required();
116 boost::shared_ptr<RouteList> r = routes.reader ();
119 _click_io->silence (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_hidden()) {
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 if (transport_sub_state & StopPendingCapture) {
158 /* force a declick out */
162 const framepos_t start_frame = _transport_frame;
163 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
165 if (_process_graph) {
166 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
167 _process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);
170 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
174 if ((*i)->is_hidden()) {
178 (*i)->set_pending_declick (declick);
182 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, b)) < 0) {
196 /** @param need_butler to be set to true by this method if it needs the butler,
197 * otherwise it must be left alone.
200 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
202 boost::shared_ptr<RouteList> r = routes.reader ();
204 const framepos_t start_frame = _transport_frame;
205 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
207 if (_process_graph) {
208 _process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
210 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
214 if ((*i)->is_hidden()) {
220 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, b)) < 0) {
235 Session::get_track_statistics ()
240 boost::shared_ptr<RouteList> rl = routes.reader();
241 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
243 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
245 if (!tr || tr->hidden()) {
249 pworst = min (pworst, tr->playback_buffer_load());
250 cworst = min (cworst, tr->capture_buffer_load());
253 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
254 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
256 if (actively_recording()) {
261 /** Process callback used when the auditioner is not active */
263 Session::process_with_events (pframes_t nframes)
268 pframes_t this_nframes;
269 framepos_t end_frame;
270 bool session_needs_butler = false;
271 framecnt_t frames_moved;
273 /* make sure the auditioner is silent */
276 auditioner->silence (nframes);
279 /* handle any pending events */
281 while (pending_events.read (&ev, 1) == 1) {
285 /* if we are not in the middle of a state change,
286 and there are immediate events queued up,
290 while (!non_realtime_work_pending() && !immediate_events.empty()) {
291 SessionEvent *ev = immediate_events.front ();
292 immediate_events.pop_front ();
296 /* Decide on what to do with quarter-frame MTC during this cycle */
298 bool const was_sending_qf_mtc = _send_qf_mtc;
299 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
301 if (_transport_speed != 0) {
303 Config->get_send_mtc () &&
304 _transport_speed >= (1 - tolerance) &&
305 _transport_speed <= (1 + tolerance)
308 if (_send_qf_mtc && !was_sending_qf_mtc) {
309 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
310 _send_timecode_update = true;
313 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
314 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
315 a quarter of a second since we sent anything at all, so send a full MTC update
318 _send_timecode_update = true;
321 _pframes_since_last_mtc += nframes;
324 /* Events caused a transport change (or we re-started sending
325 * MTC), so send an MTC Full Frame (Timecode) message. This
326 * is sent whether rolling or not, to give slaves an idea of
327 * ardour time on locates (and allow slow slaves to position
328 * and prepare for rolling)
330 if (_send_timecode_update) {
331 send_full_time_code (_transport_frame);
334 if (!process_can_proceed()) {
339 if (events.empty() || next_event == events.end()) {
340 process_without_events (nframes);
344 if (_transport_speed == 1.0) {
345 frames_moved = (framecnt_t) nframes;
347 interpolation.set_target_speed (fabs(_target_transport_speed));
348 interpolation.set_speed (fabs(_transport_speed));
349 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
352 end_frame = _transport_frame + frames_moved;
355 SessionEvent* this_event;
356 Events::iterator the_next_one;
358 if (!process_can_proceed()) {
363 if (!_exporting && _slave) {
364 if (!follow_slave (nframes)) {
369 if (_transport_speed == 0) {
374 if (!_exporting && !timecode_transmission_suspended()) {
375 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
378 framepos_t stop_limit = compute_stop_limit ();
380 if (maybe_stop (stop_limit)) {
385 this_event = *next_event;
386 the_next_one = next_event;
389 /* yes folks, here it is, the actual loop where we really truly
395 this_nframes = nframes; /* real (jack) time relative */
396 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
398 /* running an event, position transport precisely to its time */
399 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
400 /* this isn't quite right for reverse play */
401 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
402 this_nframes = abs (floor(frames_moved / _transport_speed));
407 click (_transport_frame, this_nframes);
409 if (process_routes (this_nframes, session_needs_butler)) {
414 get_track_statistics ();
416 nframes -= this_nframes;
418 if (frames_moved < 0) {
419 decrement_transport_position (-frames_moved);
421 increment_transport_position (frames_moved);
424 maybe_stop (stop_limit);
425 check_declick_out ();
428 _engine.split_cycle (this_nframes);
430 /* now handle this event and all others scheduled for the same time */
432 while (this_event && this_event->action_frame == _transport_frame) {
433 process_event (this_event);
435 if (the_next_one == events.end()) {
438 this_event = *the_next_one;
443 /* if an event left our state changing, do the right thing */
445 if (nframes && non_realtime_work_pending()) {
450 /* this is necessary to handle the case of seamless looping */
451 end_frame = _transport_frame + floor (nframes * _transport_speed);
456 } /* implicit release of route lock */
458 if (session_needs_butler) {
464 Session::reset_slave_state ()
466 average_slave_delta = 1800;
467 delta_accumulator_cnt = 0;
468 have_first_delta_accumulator = false;
469 _slave_state = Stopped;
473 Session::transport_locked () const
477 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
485 Session::follow_slave (pframes_t nframes)
488 framepos_t slave_transport_frame;
489 framecnt_t this_delta;
494 config.set_external_sync (false);
498 _slave->speed_and_position (slave_speed, slave_transport_frame);
500 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
502 if (!_slave->locked()) {
503 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
507 if (slave_transport_frame > _transport_frame) {
508 this_delta = slave_transport_frame - _transport_frame;
511 this_delta = _transport_frame - slave_transport_frame;
515 if (_slave->starting()) {
519 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
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() && !config.get_timecode_source_is_synced()) {
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 ((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 _slave_state = Running;
661 Location* al = _locations->auto_loop_location();
663 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
665 request_play_loop(false);
668 if (slave_transport_frame != _transport_frame) {
669 locate (slave_transport_frame, false, false);
679 if (_slave_state == Waiting) {
681 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
683 if (slave_transport_frame >= slave_wait_end) {
685 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
687 _slave_state = Running;
689 /* now perform a "micro-seek" within the disk buffers to realign ourselves
690 precisely with the master.
695 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
697 boost::shared_ptr<RouteList> rl = routes.reader();
698 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
699 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
700 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
707 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
708 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
710 tr->internal_playback_seek (frame_delta);
713 _transport_frame += frame_delta;
716 cerr << "cannot micro-seek\n";
720 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
721 average_slave_delta = 0L;
725 if (_slave_state == Running && _transport_speed == 0.0f) {
726 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
730 } else { // slave_speed is 0
732 /* slave has stopped */
734 if (_transport_speed != 0.0f) {
735 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
739 if (slave_transport_frame != _transport_frame) {
740 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
741 force_locate (slave_transport_frame, false);
744 _slave_state = Stopped;
749 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
751 if (slave_speed && _transport_speed) {
753 /* something isn't right, but we should move with the master
759 silent_process_routes (nframes, need_butler);
761 get_track_statistics ();
767 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
769 if (frames_moved < 0) {
770 decrement_transport_position (-frames_moved);
772 increment_transport_position (frames_moved);
775 framepos_t const stop_limit = compute_stop_limit ();
776 maybe_stop (stop_limit);
781 Session::process_without_events (pframes_t nframes)
783 bool session_needs_butler = false;
784 framecnt_t frames_moved;
786 if (!process_can_proceed()) {
791 if (!_exporting && _slave) {
792 if (!follow_slave (nframes)) {
797 if (_transport_speed == 0) {
802 if (_transport_speed == 1.0) {
803 frames_moved = (framecnt_t) nframes;
805 interpolation.set_target_speed (fabs(_target_transport_speed));
806 interpolation.set_speed (fabs(_transport_speed));
807 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
810 if (!_exporting && !timecode_transmission_suspended()) {
811 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
814 framepos_t const stop_limit = compute_stop_limit ();
816 if (maybe_stop (stop_limit)) {
821 if (maybe_sync_start (nframes)) {
825 click (_transport_frame, nframes);
827 if (process_routes (nframes, session_needs_butler)) {
832 get_track_statistics ();
834 /* XXX: I'm not sure whether this is correct, but at least it
835 matches process_with_events, so that this new frames_moved
836 is -ve when transport speed is -ve. This means that the
837 transport position is updated correctly when we are in
838 reverse. It seems a bit wrong that we're not using the
839 interpolator to compute this.
842 frames_moved = (framecnt_t) floor (_transport_speed * nframes);
844 if (frames_moved < 0) {
845 decrement_transport_position (-frames_moved);
847 increment_transport_position (frames_moved);
850 maybe_stop (stop_limit);
851 check_declick_out ();
853 if (session_needs_butler) {
858 /** Process callback used when the auditioner is active.
859 * @param nframes number of frames to process.
862 Session::process_audition (pframes_t nframes)
865 boost::shared_ptr<RouteList> r = routes.reader ();
867 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
868 if (!(*i)->is_hidden()) {
869 (*i)->silence (nframes);
873 /* run the auditioner, and if it says we need butler service, ask for it */
875 if (auditioner->play_audition (nframes) > 0) {
879 /* if using a monitor section, run it because otherwise we don't hear anything */
881 if (auditioner->needs_monitor()) {
882 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
885 /* handle pending events */
887 while (pending_events.read (&ev, 1) == 1) {
891 /* if we are not in the middle of a state change,
892 and there are immediate events queued up,
896 while (!non_realtime_work_pending() && !immediate_events.empty()) {
897 SessionEvent *ev = immediate_events.front ();
898 immediate_events.pop_front ();
902 if (!auditioner->auditioning()) {
903 /* auditioner no longer active, so go back to the normal process callback */
904 process_function = &Session::process_with_events;
909 Session::maybe_sync_start (pframes_t & nframes)
911 pframes_t sync_offset;
913 if (!waiting_for_sync_offset) {
917 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
919 /* generate silence up to the sync point, then
920 adjust nframes + offset to reflect whatever
924 no_roll (sync_offset);
925 nframes -= sync_offset;
926 Port::increment_global_port_buffer_offset (sync_offset);
927 waiting_for_sync_offset = false;
930 return true; // done, nothing left to process
935 /* sync offset point is not within this process()
936 cycle, so just generate silence. and don't bother
937 with any fancy stuff here, just the minimal silence.
942 if (Config->get_locate_while_waiting_for_sync()) {
943 if (micro_locate (nframes)) {
944 /* XXX ERROR !!! XXX */
948 return true; // done, nothing left to process
955 Session::queue_event (SessionEvent* ev)
957 if (_state_of_the_state & Deletion) {
959 } else if (_state_of_the_state & Loading) {
962 pending_events.write (&ev, 1);
967 Session::set_next_event ()
969 if (events.empty()) {
970 next_event = events.end();
974 if (next_event == events.end()) {
975 next_event = events.begin();
978 if ((*next_event)->action_frame > _transport_frame) {
979 next_event = events.begin();
982 for (; next_event != events.end(); ++next_event) {
983 if ((*next_event)->action_frame >= _transport_frame) {
990 Session::process_event (SessionEvent* ev)
995 /* if we're in the middle of a state change (i.e. waiting
996 for the butler thread to complete the non-realtime
997 part of the change), we'll just have to queue this
998 event for a time when the change is complete.
1001 if (non_realtime_work_pending()) {
1003 /* except locates, which we have the capability to handle */
1005 if (ev->type != SessionEvent::Locate) {
1006 immediate_events.insert (immediate_events.end(), ev);
1012 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1015 case SessionEvent::SetLoop:
1016 set_play_loop (ev->yes_or_no);
1019 case SessionEvent::AutoLoop:
1021 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1027 case SessionEvent::Locate:
1028 if (ev->yes_or_no) {
1029 // cerr << "forced locate to " << ev->target_frame << endl;
1030 locate (ev->target_frame, false, true, false);
1032 // cerr << "soft locate to " << ev->target_frame << endl;
1033 start_locate (ev->target_frame, false, true, false);
1035 _send_timecode_update = true;
1038 case SessionEvent::LocateRoll:
1039 if (ev->yes_or_no) {
1040 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1041 locate (ev->target_frame, true, true, false);
1043 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1044 start_locate (ev->target_frame, true, true, false);
1046 _send_timecode_update = true;
1049 case SessionEvent::LocateRollLocate:
1050 // locate is handled by ::request_roll_at_and_return()
1051 _requested_return_frame = ev->target_frame;
1052 request_locate (ev->target2_frame, true);
1056 case SessionEvent::SetTransportSpeed:
1057 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1060 case SessionEvent::PunchIn:
1061 // cerr << "PunchIN at " << transport_frame() << endl;
1062 if (config.get_punch_in() && record_status() == Enabled) {
1069 case SessionEvent::PunchOut:
1070 // cerr << "PunchOUT at " << transport_frame() << endl;
1071 if (config.get_punch_out()) {
1072 step_back_from_record ();
1078 case SessionEvent::StopOnce:
1079 if (!non_realtime_work_pending()) {
1080 stop_transport (ev->yes_or_no);
1081 _clear_event_type (SessionEvent::StopOnce);
1087 case SessionEvent::RangeStop:
1088 if (!non_realtime_work_pending()) {
1089 stop_transport (ev->yes_or_no);
1095 case SessionEvent::RangeLocate:
1096 start_locate (ev->target_frame, true, true, false);
1101 case SessionEvent::Overwrite:
1102 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1105 case SessionEvent::SetTrackSpeed:
1106 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1109 case SessionEvent::SetSyncSource:
1110 use_sync_source (ev->slave);
1113 case SessionEvent::Audition:
1114 set_audition (ev->region);
1115 // drop reference to region
1116 ev->region.reset ();
1119 case SessionEvent::InputConfigurationChange:
1120 add_post_transport_work (PostTransportInputChange);
1121 _butler->schedule_transport_work ();
1124 case SessionEvent::SetPlayAudioRange:
1125 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1128 case SessionEvent::RealTimeOperation:
1130 del = false; // other side of RT request needs to clean up
1133 case SessionEvent::AdjustPlaybackBuffering:
1134 schedule_playback_buffering_adjustment ();
1137 case SessionEvent::AdjustCaptureBuffering:
1138 schedule_capture_buffering_adjustment ();
1141 case SessionEvent::SetTimecodeTransmission:
1142 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1146 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1152 del = del && !_remove_event (ev);
1161 Session::compute_stop_limit () const
1163 if (!Config->get_stop_at_session_end ()) {
1164 return max_framepos;
1167 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1168 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1170 if (actively_recording ()) {
1171 /* permanently recording */
1172 return max_framepos;
1173 } else if (punching_in && !punching_out) {
1174 /* punching in but never out */
1175 return max_framepos;
1176 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_frame()) {
1177 /* punching in and punching out after session end */
1178 return max_framepos;
1181 return current_end_frame ();