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"
42 #include "midi++/manager.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 MIDI::Manager::instance()->cycle_start(nframes);
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 // the ticker is for sending time information like MidiClock
80 framepos_t transport_frames = transport_frame();
81 Timecode::BBT_Time transport_bbt;
82 bbt_time(transport_frames, transport_bbt);
83 Timecode::Time transport_timecode;
84 timecode_time(transport_frames, transport_timecode);
85 tick (transport_frames, transport_bbt, transport_timecode); /* EMIT SIGNAL */
87 SendFeedback (); /* EMIT SIGNAL */
89 MIDI::Manager::instance()->cycle_end();
93 Session::fail_roll (pframes_t nframes)
95 return no_roll (nframes);
99 Session::no_roll (pframes_t nframes)
101 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
103 bool declick = get_transport_declick_required();
104 boost::shared_ptr<RouteList> r = routes.reader ();
107 _click_io->silence (nframes);
110 if (_process_graph->threads_in_use() > 0) {
111 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
112 _process_graph->routes_no_roll( nframes, _transport_frame, end_frame, non_realtime_work_pending(), declick);
114 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
116 if ((*i)->is_hidden()) {
120 (*i)->set_pending_declick (declick);
122 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending())) {
123 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
134 Session::process_routes (pframes_t nframes, bool& need_butler)
136 int declick = get_transport_declick_required();
137 boost::shared_ptr<RouteList> r = routes.reader ();
139 if (transport_sub_state & StopPendingCapture) {
140 /* force a declick out */
144 const framepos_t start_frame = _transport_frame;
145 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
147 /* XXX this is hack to force use of the graph even if we are only
148 using 1 thread. its needed because otherwise when we remove
149 tracks, the graph never gets updated.
151 if (1 || _process_graph->threads_in_use() > 0) {
152 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
153 _process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);
156 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
160 if ((*i)->is_hidden()) {
164 (*i)->set_pending_declick (declick);
166 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, need_butler)) < 0) {
177 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
179 boost::shared_ptr<RouteList> r = routes.reader ();
181 const framepos_t start_frame = _transport_frame;
182 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
184 /* XXX this is hack to force use of the graph even if we are only
185 using 1 thread. its needed because otherwise when we remove
186 tracks, the graph never gets updated.
188 if (1 || _process_graph->threads_in_use() > 0) {
189 _process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
191 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
195 if ((*i)->is_hidden()) {
199 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, need_butler)) < 0) {
210 Session::get_track_statistics ()
215 boost::shared_ptr<RouteList> rl = routes.reader();
216 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
218 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
220 if (!tr || tr->hidden()) {
224 pworst = min (pworst, tr->playback_buffer_load());
225 cworst = min (cworst, tr->capture_buffer_load());
228 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
229 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
231 if (actively_recording()) {
236 /** Process callback used when the auditioner is not active */
238 Session::process_with_events (pframes_t nframes)
241 pframes_t this_nframes;
242 framepos_t end_frame;
243 bool session_needs_butler = false;
244 framecnt_t frames_moved;
246 /* make sure the auditioner is silent */
249 auditioner->silence (nframes);
252 /* handle any pending events */
254 while (pending_events.read (&ev, 1) == 1) {
258 /* if we are not in the middle of a state change,
259 and there are immediate events queued up,
263 while (!non_realtime_work_pending() && !immediate_events.empty()) {
264 SessionEvent *ev = immediate_events.front ();
265 immediate_events.pop_front ();
269 /* Decide on what to do with quarter-frame MTC during this cycle */
271 bool const was_sending_qf_mtc = _send_qf_mtc;
272 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
274 if (_transport_speed != 0) {
276 Config->get_send_mtc () &&
277 _transport_speed >= (1 - tolerance) &&
278 _transport_speed <= (1 + tolerance)
281 if (_send_qf_mtc && !was_sending_qf_mtc) {
282 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
283 _send_timecode_update = true;
286 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
287 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
288 a quarter of a second since we sent anything at all, so send a full MTC update
291 _send_timecode_update = true;
294 _pframes_since_last_mtc += nframes;
297 /* Events caused a transport change (or we re-started sending
298 * MTC), so send an MTC Full Frame (Timecode) message. This
299 * is sent whether rolling or not, to give slaves an idea of
300 * ardour time on locates (and allow slow slaves to position
301 * and prepare for rolling)
303 if (_send_timecode_update) {
304 send_full_time_code (_transport_frame);
307 if (!process_can_proceed()) {
312 if (events.empty() || next_event == events.end()) {
313 process_without_events (nframes);
317 if (_transport_speed == 1.0) {
318 frames_moved = (framecnt_t) nframes;
320 interpolation.set_target_speed (fabs(_target_transport_speed));
321 interpolation.set_speed (fabs(_transport_speed));
322 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
325 end_frame = _transport_frame + frames_moved;
328 SessionEvent* this_event;
329 Events::iterator the_next_one;
331 if (!process_can_proceed()) {
336 if (!_exporting && _slave) {
337 if (!follow_slave (nframes)) {
342 if (_transport_speed == 0) {
347 if (!_exporting && !timecode_transmission_suspended()) {
348 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
351 framepos_t stop_limit = compute_stop_limit ();
353 if (maybe_stop (stop_limit)) {
358 this_event = *next_event;
359 the_next_one = next_event;
362 /* yes folks, here it is, the actual loop where we really truly
368 this_nframes = nframes; /* real (jack) time relative */
369 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
371 /* running an event, position transport precisely to its time */
372 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
373 /* this isn't quite right for reverse play */
374 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
375 this_nframes = abs (floor(frames_moved / _transport_speed));
380 click (_transport_frame, this_nframes);
382 if (process_routes (this_nframes, session_needs_butler)) {
387 get_track_statistics ();
389 nframes -= this_nframes;
391 if (frames_moved < 0) {
392 decrement_transport_position (-frames_moved);
394 increment_transport_position (frames_moved);
397 maybe_stop (stop_limit);
398 check_declick_out ();
401 _engine.split_cycle (this_nframes);
403 /* now handle this event and all others scheduled for the same time */
405 while (this_event && this_event->action_frame == _transport_frame) {
406 process_event (this_event);
408 if (the_next_one == events.end()) {
411 this_event = *the_next_one;
416 /* if an event left our state changing, do the right thing */
418 if (nframes && non_realtime_work_pending()) {
423 /* this is necessary to handle the case of seamless looping */
424 end_frame = _transport_frame + floor (nframes * _transport_speed);
429 } /* implicit release of route lock */
431 if (session_needs_butler) {
437 Session::reset_slave_state ()
439 average_slave_delta = 1800;
440 delta_accumulator_cnt = 0;
441 have_first_delta_accumulator = false;
442 _slave_state = Stopped;
446 Session::transport_locked () const
450 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
458 Session::follow_slave (pframes_t nframes)
461 framepos_t slave_transport_frame;
462 framecnt_t this_delta;
467 config.set_external_sync (false);
471 _slave->speed_and_position (slave_speed, slave_transport_frame);
473 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
475 if (!_slave->locked()) {
476 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
480 if (slave_transport_frame > _transport_frame) {
481 this_delta = slave_transport_frame - _transport_frame;
484 this_delta = _transport_frame - slave_transport_frame;
488 if (_slave->starting()) {
492 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
494 /* if the TC source is synced, then we assume that its
495 speed is binary: 0.0 or 1.0
498 if (slave_speed != 0.0f) {
504 /* if we are chasing and the average delta between us and the
505 master gets too big, we want to switch to silent
506 motion. so keep track of that here.
509 if (_slave_state == Running) {
510 calculate_moving_average_of_slave_delta(dir, this_delta);
514 track_slave_state (slave_speed, slave_transport_frame, this_delta);
516 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
517 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
520 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
522 if (_transport_speed != 0.0f) {
525 note that average_dir is +1 or -1
530 if (average_slave_delta == 0) {
534 delta = average_slave_delta;
535 delta *= average_dir;
539 if (slave_speed != 0.0) {
540 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
541 (int) (dir * this_delta),
545 slave_transport_frame,
546 average_slave_delta));
550 if (_slave->give_slave_full_control_over_transport_speed()) {
551 set_transport_speed (slave_speed, false, false);
552 //std::cout << "set speed = " << slave_speed << "\n";
554 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
555 request_transport_speed (adjusted_speed);
556 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
557 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
562 if ((framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
563 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
571 if (_slave_state == Running && !non_realtime_work_pending()) {
572 /* speed is set, we're locked, and good to go */
577 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
578 follow_slave_silently (nframes, slave_speed);
581 /* don't move at all */
582 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
588 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
590 if (delta_accumulator_cnt >= delta_accumulator_size) {
591 have_first_delta_accumulator = true;
592 delta_accumulator_cnt = 0;
595 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
596 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
599 if (have_first_delta_accumulator) {
600 average_slave_delta = 0L;
601 for (int i = 0; i < delta_accumulator_size; ++i) {
602 average_slave_delta += delta_accumulator[i];
604 average_slave_delta /= (int32_t) delta_accumulator_size;
605 if (average_slave_delta < 0L) {
607 average_slave_delta = abs(average_slave_delta);
615 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t /*this_delta*/)
617 if (slave_speed != 0.0f) {
619 /* slave is running */
621 switch (_slave_state) {
623 if (_slave->requires_seekahead()) {
624 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
625 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
626 /* we can call locate() here because we are in process context */
627 locate (slave_wait_end, false, false);
628 _slave_state = Waiting;
632 _slave_state = Running;
634 Location* al = _locations->auto_loop_location();
636 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
638 request_play_loop(false);
641 if (slave_transport_frame != _transport_frame) {
642 locate (slave_transport_frame, false, false);
652 if (_slave_state == Waiting) {
654 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
656 if (slave_transport_frame >= slave_wait_end) {
658 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
660 _slave_state = Running;
662 /* now perform a "micro-seek" within the disk buffers to realign ourselves
663 precisely with the master.
668 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
670 boost::shared_ptr<RouteList> rl = routes.reader();
671 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
672 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
673 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
680 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
681 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
683 tr->internal_playback_seek (frame_delta);
686 _transport_frame += frame_delta;
689 cerr << "cannot micro-seek\n";
693 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
694 average_slave_delta = 0L;
698 if (_slave_state == Running && _transport_speed == 0.0f) {
699 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
703 } else { // slave_speed is 0
705 /* slave has stopped */
707 if (_transport_speed != 0.0f) {
708 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
712 if (slave_transport_frame != _transport_frame) {
713 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
714 force_locate (slave_transport_frame, false);
717 _slave_state = Stopped;
722 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
724 if (slave_speed && _transport_speed) {
726 /* something isn't right, but we should move with the master
732 silent_process_routes (nframes, need_butler);
734 get_track_statistics ();
740 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
742 if (frames_moved < 0) {
743 decrement_transport_position (-frames_moved);
745 increment_transport_position (frames_moved);
748 framepos_t const stop_limit = compute_stop_limit ();
749 maybe_stop (stop_limit);
754 Session::process_without_events (pframes_t nframes)
756 bool session_needs_butler = false;
757 framecnt_t frames_moved;
759 if (!process_can_proceed()) {
764 if (!_exporting && _slave) {
765 if (!follow_slave (nframes)) {
770 if (_transport_speed == 0) {
775 if (_transport_speed == 1.0) {
776 frames_moved = (framecnt_t) nframes;
778 interpolation.set_target_speed (fabs(_target_transport_speed));
779 interpolation.set_speed (fabs(_transport_speed));
780 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
783 if (!_exporting && !timecode_transmission_suspended()) {
784 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
787 framepos_t const stop_limit = compute_stop_limit ();
789 if (maybe_stop (stop_limit)) {
794 if (maybe_sync_start (nframes)) {
798 click (_transport_frame, nframes);
800 if (process_routes (nframes, session_needs_butler)) {
805 get_track_statistics ();
807 /* XXX: I'm not sure whether this is correct, but at least it
808 matches process_with_events, so that this new frames_moved
809 is -ve when transport speed is -ve. This means that the
810 transport position is updated correctly when we are in
811 reverse. It seems a bit wrong that we're not using the
812 interpolator to compute this.
815 frames_moved = (framecnt_t) floor (_transport_speed * nframes);
817 if (frames_moved < 0) {
818 decrement_transport_position (-frames_moved);
820 increment_transport_position (frames_moved);
823 maybe_stop (stop_limit);
824 check_declick_out ();
826 if (session_needs_butler) {
831 /** Process callback used when the auditioner is active.
832 * @param nframes number of frames to process.
835 Session::process_audition (pframes_t nframes)
838 boost::shared_ptr<RouteList> r = routes.reader ();
840 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
841 if (!(*i)->is_hidden()) {
842 (*i)->silence (nframes);
846 /* run the auditioner, and if it says we need butler service, ask for it */
848 if (auditioner->play_audition (nframes) > 0) {
852 /* if using a monitor section, run it because otherwise we don't hear anything */
854 if (auditioner->needs_monitor()) {
855 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
858 /* handle pending events */
860 while (pending_events.read (&ev, 1) == 1) {
864 /* if we are not in the middle of a state change,
865 and there are immediate events queued up,
869 while (!non_realtime_work_pending() && !immediate_events.empty()) {
870 SessionEvent *ev = immediate_events.front ();
871 immediate_events.pop_front ();
875 if (!auditioner->auditioning()) {
876 /* auditioner no longer active, so go back to the normal process callback */
877 process_function = &Session::process_with_events;
882 Session::maybe_sync_start (pframes_t & nframes)
884 pframes_t sync_offset;
886 if (!waiting_for_sync_offset) {
890 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
892 /* generate silence up to the sync point, then
893 adjust nframes + offset to reflect whatever
897 no_roll (sync_offset);
898 nframes -= sync_offset;
899 Port::increment_global_port_buffer_offset (sync_offset);
900 waiting_for_sync_offset = false;
903 return true; // done, nothing left to process
908 /* sync offset point is not within this process()
909 cycle, so just generate silence. and don't bother
910 with any fancy stuff here, just the minimal silence.
915 if (Config->get_locate_while_waiting_for_sync()) {
916 if (micro_locate (nframes)) {
917 /* XXX ERROR !!! XXX */
921 return true; // done, nothing left to process
928 Session::queue_event (SessionEvent* ev)
930 if (_state_of_the_state & Deletion) {
932 } else if (_state_of_the_state & Loading) {
935 pending_events.write (&ev, 1);
940 Session::set_next_event ()
942 if (events.empty()) {
943 next_event = events.end();
947 if (next_event == events.end()) {
948 next_event = events.begin();
951 if ((*next_event)->action_frame > _transport_frame) {
952 next_event = events.begin();
955 for (; next_event != events.end(); ++next_event) {
956 if ((*next_event)->action_frame >= _transport_frame) {
963 Session::process_event (SessionEvent* ev)
968 /* if we're in the middle of a state change (i.e. waiting
969 for the butler thread to complete the non-realtime
970 part of the change), we'll just have to queue this
971 event for a time when the change is complete.
974 if (non_realtime_work_pending()) {
976 /* except locates, which we have the capability to handle */
978 if (ev->type != SessionEvent::Locate) {
979 immediate_events.insert (immediate_events.end(), ev);
985 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
988 case SessionEvent::SetLoop:
989 set_play_loop (ev->yes_or_no);
992 case SessionEvent::AutoLoop:
994 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1000 case SessionEvent::Locate:
1001 if (ev->yes_or_no) {
1002 // cerr << "forced locate to " << ev->target_frame << endl;
1003 locate (ev->target_frame, false, true, false);
1005 // cerr << "soft locate to " << ev->target_frame << endl;
1006 start_locate (ev->target_frame, false, true, false);
1008 _send_timecode_update = true;
1011 case SessionEvent::LocateRoll:
1012 if (ev->yes_or_no) {
1013 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1014 locate (ev->target_frame, true, true, false);
1016 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1017 start_locate (ev->target_frame, true, true, false);
1019 _send_timecode_update = true;
1022 case SessionEvent::LocateRollLocate:
1023 // locate is handled by ::request_roll_at_and_return()
1024 _requested_return_frame = ev->target_frame;
1025 request_locate (ev->target2_frame, true);
1029 case SessionEvent::SetTransportSpeed:
1030 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1033 case SessionEvent::PunchIn:
1034 // cerr << "PunchIN at " << transport_frame() << endl;
1035 if (config.get_punch_in() && record_status() == Enabled) {
1042 case SessionEvent::PunchOut:
1043 // cerr << "PunchOUT at " << transport_frame() << endl;
1044 if (config.get_punch_out()) {
1045 step_back_from_record ();
1051 case SessionEvent::StopOnce:
1052 if (!non_realtime_work_pending()) {
1053 stop_transport (ev->yes_or_no);
1054 _clear_event_type (SessionEvent::StopOnce);
1060 case SessionEvent::RangeStop:
1061 if (!non_realtime_work_pending()) {
1062 stop_transport (ev->yes_or_no);
1068 case SessionEvent::RangeLocate:
1069 start_locate (ev->target_frame, true, true, false);
1074 case SessionEvent::Overwrite:
1075 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1078 case SessionEvent::SetTrackSpeed:
1079 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1082 case SessionEvent::SetSyncSource:
1083 use_sync_source (ev->slave);
1086 case SessionEvent::Audition:
1087 set_audition (ev->region);
1088 // drop reference to region
1089 ev->region.reset ();
1092 case SessionEvent::InputConfigurationChange:
1093 add_post_transport_work (PostTransportInputChange);
1094 _butler->schedule_transport_work ();
1097 case SessionEvent::SetPlayAudioRange:
1098 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1101 case SessionEvent::RealTimeOperation:
1103 del = false; // other side of RT request needs to clean up
1106 case SessionEvent::AdjustPlaybackBuffering:
1107 schedule_playback_buffering_adjustment ();
1110 case SessionEvent::AdjustCaptureBuffering:
1111 schedule_capture_buffering_adjustment ();
1114 case SessionEvent::SetTimecodeTransmission:
1115 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1119 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1125 del = del && !_remove_event (ev);
1134 Session::compute_stop_limit () const
1136 bool const punching = (config.get_punch_in () && _locations->auto_punch_location());
1138 if (!actively_recording() && !punching && Config->get_stop_at_session_end()) {
1139 return current_end_frame ();
1142 return max_framepos;