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/cycle_timer.h"
44 #include "midi++/manager.h"
45 #include "midi++/mmc.h"
49 using namespace ARDOUR;
53 /** Called by the audio engine when there is work to be done with JACK.
54 * @param nframes Number of frames to process.
58 Session::process (pframes_t nframes)
60 MIDI::Manager::instance()->cycle_start(nframes);
64 if (processing_blocked()) {
69 if (non_realtime_work_pending()) {
70 if (!_butler->transport_work_requested ()) {
75 _engine.main_thread()->get_buffers ();
77 (this->*process_function) (nframes);
79 _engine.main_thread()->drop_buffers ();
81 // the ticker is for sending time information like MidiClock
82 framepos_t transport_frames = transport_frame();
83 Timecode::BBT_Time transport_bbt;
85 _tempo_map->bbt_time_rt (transport_frames, transport_bbt);
86 Timecode::Time transport_timecode;
87 timecode_time(transport_frames, transport_timecode);
88 tick (transport_frames, transport_bbt, transport_timecode); /* EMIT SIGNAL */
90 /* don't bother with a message */
93 SendFeedback (); /* EMIT SIGNAL */
95 MIDI::Manager::instance()->cycle_end();
99 Session::fail_roll (pframes_t nframes)
101 return no_roll (nframes);
105 Session::no_roll (pframes_t nframes)
109 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
111 bool declick = get_transport_declick_required();
112 boost::shared_ptr<RouteList> r = routes.reader ();
115 _click_io->silence (nframes);
118 if (1 || _process_graph->threads_in_use() > 0) {
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_hidden()) {
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);
145 Session::process_routes (pframes_t nframes, bool& need_butler)
147 int declick = get_transport_declick_required();
148 boost::shared_ptr<RouteList> r = routes.reader ();
150 if (transport_sub_state & StopPendingCapture) {
151 /* force a declick out */
155 const framepos_t start_frame = _transport_frame;
156 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
158 /* XXX this is hack to force use of the graph even if we are only
159 using 1 thread. its needed because otherwise when we remove
160 tracks, the graph never gets updated.
162 if (1 || _process_graph->threads_in_use() > 0) {
163 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
164 _process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);
167 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
171 if ((*i)->is_hidden()) {
175 (*i)->set_pending_declick (declick);
177 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, need_butler)) < 0) {
188 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
190 boost::shared_ptr<RouteList> r = routes.reader ();
192 const framepos_t start_frame = _transport_frame;
193 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
195 /* XXX this is hack to force use of the graph even if we are only
196 using 1 thread. its needed because otherwise when we remove
197 tracks, the graph never gets updated.
199 if (1 || _process_graph->threads_in_use() > 0) {
200 _process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
202 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
206 if ((*i)->is_hidden()) {
210 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, need_butler)) < 0) {
221 Session::get_track_statistics ()
226 boost::shared_ptr<RouteList> rl = routes.reader();
227 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
229 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
231 if (!tr || tr->hidden()) {
235 pworst = min (pworst, tr->playback_buffer_load());
236 cworst = min (cworst, tr->capture_buffer_load());
239 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
240 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
242 if (actively_recording()) {
247 /** Process callback used when the auditioner is not active */
249 Session::process_with_events (pframes_t nframes)
254 pframes_t this_nframes;
255 framepos_t end_frame;
256 bool session_needs_butler = false;
257 framecnt_t frames_moved;
259 /* make sure the auditioner is silent */
262 auditioner->silence (nframes);
265 /* handle any pending events */
267 while (pending_events.read (&ev, 1) == 1) {
271 /* if we are not in the middle of a state change,
272 and there are immediate events queued up,
276 while (!non_realtime_work_pending() && !immediate_events.empty()) {
277 SessionEvent *ev = immediate_events.front ();
278 immediate_events.pop_front ();
282 /* Decide on what to do with quarter-frame MTC during this cycle */
284 bool const was_sending_qf_mtc = _send_qf_mtc;
285 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
287 if (_transport_speed != 0) {
289 Config->get_send_mtc () &&
290 _transport_speed >= (1 - tolerance) &&
291 _transport_speed <= (1 + tolerance)
294 if (_send_qf_mtc && !was_sending_qf_mtc) {
295 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
296 _send_timecode_update = true;
299 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
300 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
301 a quarter of a second since we sent anything at all, so send a full MTC update
304 _send_timecode_update = true;
307 _pframes_since_last_mtc += nframes;
310 /* Events caused a transport change (or we re-started sending
311 * MTC), so send an MTC Full Frame (Timecode) message. This
312 * is sent whether rolling or not, to give slaves an idea of
313 * ardour time on locates (and allow slow slaves to position
314 * and prepare for rolling)
316 if (_send_timecode_update) {
317 send_full_time_code (_transport_frame);
320 if (!process_can_proceed()) {
325 if (events.empty() || next_event == events.end()) {
326 process_without_events (nframes);
330 if (_transport_speed == 1.0) {
331 frames_moved = (framecnt_t) nframes;
333 interpolation.set_target_speed (fabs(_target_transport_speed));
334 interpolation.set_speed (fabs(_transport_speed));
335 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
338 end_frame = _transport_frame + frames_moved;
341 SessionEvent* this_event;
342 Events::iterator the_next_one;
344 if (!process_can_proceed()) {
349 if (!_exporting && _slave) {
350 if (!follow_slave (nframes)) {
355 if (_transport_speed == 0) {
360 if (!_exporting && !timecode_transmission_suspended()) {
361 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
364 framepos_t stop_limit = compute_stop_limit ();
366 if (maybe_stop (stop_limit)) {
371 this_event = *next_event;
372 the_next_one = next_event;
375 /* yes folks, here it is, the actual loop where we really truly
381 this_nframes = nframes; /* real (jack) time relative */
382 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
384 /* running an event, position transport precisely to its time */
385 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
386 /* this isn't quite right for reverse play */
387 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
388 this_nframes = abs (floor(frames_moved / _transport_speed));
393 click (_transport_frame, this_nframes);
395 if (process_routes (this_nframes, session_needs_butler)) {
400 get_track_statistics ();
402 nframes -= this_nframes;
404 if (frames_moved < 0) {
405 decrement_transport_position (-frames_moved);
407 increment_transport_position (frames_moved);
410 maybe_stop (stop_limit);
411 check_declick_out ();
414 _engine.split_cycle (this_nframes);
416 /* now handle this event and all others scheduled for the same time */
418 while (this_event && this_event->action_frame == _transport_frame) {
419 process_event (this_event);
421 if (the_next_one == events.end()) {
424 this_event = *the_next_one;
429 /* if an event left our state changing, do the right thing */
431 if (nframes && non_realtime_work_pending()) {
436 /* this is necessary to handle the case of seamless looping */
437 end_frame = _transport_frame + floor (nframes * _transport_speed);
442 } /* implicit release of route lock */
444 if (session_needs_butler) {
450 Session::reset_slave_state ()
452 average_slave_delta = 1800;
453 delta_accumulator_cnt = 0;
454 have_first_delta_accumulator = false;
455 _slave_state = Stopped;
459 Session::transport_locked () const
463 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
471 Session::follow_slave (pframes_t nframes)
474 framepos_t slave_transport_frame;
475 framecnt_t this_delta;
480 config.set_external_sync (false);
484 _slave->speed_and_position (slave_speed, slave_transport_frame);
486 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
488 if (!_slave->locked()) {
489 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
493 if (slave_transport_frame > _transport_frame) {
494 this_delta = slave_transport_frame - _transport_frame;
497 this_delta = _transport_frame - slave_transport_frame;
501 if (_slave->starting()) {
505 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
507 /* if the TC source is synced, then we assume that its
508 speed is binary: 0.0 or 1.0
511 if (slave_speed != 0.0f) {
517 /* if we are chasing and the average delta between us and the
518 master gets too big, we want to switch to silent
519 motion. so keep track of that here.
522 if (_slave_state == Running) {
523 calculate_moving_average_of_slave_delta(dir, this_delta);
527 track_slave_state (slave_speed, slave_transport_frame, this_delta);
529 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
530 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
533 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
535 if (_transport_speed != 0.0f) {
538 note that average_dir is +1 or -1
543 if (average_slave_delta == 0) {
547 delta = average_slave_delta;
548 delta *= average_dir;
552 if (slave_speed != 0.0) {
553 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
554 (int) (dir * this_delta),
558 slave_transport_frame,
559 average_slave_delta));
563 if (_slave->give_slave_full_control_over_transport_speed()) {
564 set_transport_speed (slave_speed, false, false);
565 //std::cout << "set speed = " << slave_speed << "\n";
567 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
568 request_transport_speed (adjusted_speed);
569 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
570 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
575 if ((framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
576 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
584 if (_slave_state == Running && !non_realtime_work_pending()) {
585 /* speed is set, we're locked, and good to go */
590 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
591 follow_slave_silently (nframes, slave_speed);
594 /* don't move at all */
595 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
601 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
603 if (delta_accumulator_cnt >= delta_accumulator_size) {
604 have_first_delta_accumulator = true;
605 delta_accumulator_cnt = 0;
608 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
609 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
612 if (have_first_delta_accumulator) {
613 average_slave_delta = 0L;
614 for (int i = 0; i < delta_accumulator_size; ++i) {
615 average_slave_delta += delta_accumulator[i];
617 average_slave_delta /= (int32_t) delta_accumulator_size;
618 if (average_slave_delta < 0L) {
620 average_slave_delta = abs(average_slave_delta);
628 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t /*this_delta*/)
630 if (slave_speed != 0.0f) {
632 /* slave is running */
634 switch (_slave_state) {
636 if (_slave->requires_seekahead()) {
637 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
638 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
639 /* we can call locate() here because we are in process context */
640 locate (slave_wait_end, false, false);
641 _slave_state = Waiting;
645 _slave_state = Running;
647 Location* al = _locations->auto_loop_location();
649 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
651 request_play_loop(false);
654 if (slave_transport_frame != _transport_frame) {
655 locate (slave_transport_frame, false, false);
665 if (_slave_state == Waiting) {
667 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
669 if (slave_transport_frame >= slave_wait_end) {
671 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
673 _slave_state = Running;
675 /* now perform a "micro-seek" within the disk buffers to realign ourselves
676 precisely with the master.
681 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
683 boost::shared_ptr<RouteList> rl = routes.reader();
684 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
685 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
686 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
693 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
694 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
696 tr->internal_playback_seek (frame_delta);
699 _transport_frame += frame_delta;
702 cerr << "cannot micro-seek\n";
706 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
707 average_slave_delta = 0L;
711 if (_slave_state == Running && _transport_speed == 0.0f) {
712 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
716 } else { // slave_speed is 0
718 /* slave has stopped */
720 if (_transport_speed != 0.0f) {
721 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
725 if (slave_transport_frame != _transport_frame) {
726 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
727 force_locate (slave_transport_frame, false);
730 _slave_state = Stopped;
735 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
737 if (slave_speed && _transport_speed) {
739 /* something isn't right, but we should move with the master
745 silent_process_routes (nframes, need_butler);
747 get_track_statistics ();
753 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
755 if (frames_moved < 0) {
756 decrement_transport_position (-frames_moved);
758 increment_transport_position (frames_moved);
761 framepos_t const stop_limit = compute_stop_limit ();
762 maybe_stop (stop_limit);
767 Session::process_without_events (pframes_t nframes)
769 bool session_needs_butler = false;
770 framecnt_t frames_moved;
772 if (!process_can_proceed()) {
777 if (!_exporting && _slave) {
778 if (!follow_slave (nframes)) {
783 if (_transport_speed == 0) {
788 if (_transport_speed == 1.0) {
789 frames_moved = (framecnt_t) nframes;
791 interpolation.set_target_speed (fabs(_target_transport_speed));
792 interpolation.set_speed (fabs(_transport_speed));
793 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
796 if (!_exporting && !timecode_transmission_suspended()) {
797 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
800 framepos_t const stop_limit = compute_stop_limit ();
802 if (maybe_stop (stop_limit)) {
807 if (maybe_sync_start (nframes)) {
811 click (_transport_frame, nframes);
813 if (process_routes (nframes, session_needs_butler)) {
818 get_track_statistics ();
820 /* XXX: I'm not sure whether this is correct, but at least it
821 matches process_with_events, so that this new frames_moved
822 is -ve when transport speed is -ve. This means that the
823 transport position is updated correctly when we are in
824 reverse. It seems a bit wrong that we're not using the
825 interpolator to compute this.
828 frames_moved = (framecnt_t) floor (_transport_speed * nframes);
830 if (frames_moved < 0) {
831 decrement_transport_position (-frames_moved);
833 increment_transport_position (frames_moved);
836 maybe_stop (stop_limit);
837 check_declick_out ();
839 if (session_needs_butler) {
844 /** Process callback used when the auditioner is active.
845 * @param nframes number of frames to process.
848 Session::process_audition (pframes_t nframes)
851 boost::shared_ptr<RouteList> r = routes.reader ();
853 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
854 if (!(*i)->is_hidden()) {
855 (*i)->silence (nframes);
859 /* run the auditioner, and if it says we need butler service, ask for it */
861 if (auditioner->play_audition (nframes) > 0) {
865 /* if using a monitor section, run it because otherwise we don't hear anything */
867 if (auditioner->needs_monitor()) {
868 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
871 /* handle pending events */
873 while (pending_events.read (&ev, 1) == 1) {
877 /* if we are not in the middle of a state change,
878 and there are immediate events queued up,
882 while (!non_realtime_work_pending() && !immediate_events.empty()) {
883 SessionEvent *ev = immediate_events.front ();
884 immediate_events.pop_front ();
888 if (!auditioner->auditioning()) {
889 /* auditioner no longer active, so go back to the normal process callback */
890 process_function = &Session::process_with_events;
895 Session::maybe_sync_start (pframes_t & nframes)
897 pframes_t sync_offset;
899 if (!waiting_for_sync_offset) {
903 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
905 /* generate silence up to the sync point, then
906 adjust nframes + offset to reflect whatever
910 no_roll (sync_offset);
911 nframes -= sync_offset;
912 Port::increment_global_port_buffer_offset (sync_offset);
913 waiting_for_sync_offset = false;
916 return true; // done, nothing left to process
921 /* sync offset point is not within this process()
922 cycle, so just generate silence. and don't bother
923 with any fancy stuff here, just the minimal silence.
928 if (Config->get_locate_while_waiting_for_sync()) {
929 if (micro_locate (nframes)) {
930 /* XXX ERROR !!! XXX */
934 return true; // done, nothing left to process
941 Session::queue_event (SessionEvent* ev)
943 if (_state_of_the_state & Deletion) {
945 } else if (_state_of_the_state & Loading) {
948 pending_events.write (&ev, 1);
953 Session::set_next_event ()
955 if (events.empty()) {
956 next_event = events.end();
960 if (next_event == events.end()) {
961 next_event = events.begin();
964 if ((*next_event)->action_frame > _transport_frame) {
965 next_event = events.begin();
968 for (; next_event != events.end(); ++next_event) {
969 if ((*next_event)->action_frame >= _transport_frame) {
976 Session::process_event (SessionEvent* ev)
981 /* if we're in the middle of a state change (i.e. waiting
982 for the butler thread to complete the non-realtime
983 part of the change), we'll just have to queue this
984 event for a time when the change is complete.
987 if (non_realtime_work_pending()) {
989 /* except locates, which we have the capability to handle */
991 if (ev->type != SessionEvent::Locate) {
992 immediate_events.insert (immediate_events.end(), ev);
998 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1001 case SessionEvent::SetLoop:
1002 set_play_loop (ev->yes_or_no);
1005 case SessionEvent::AutoLoop:
1007 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1013 case SessionEvent::Locate:
1014 if (ev->yes_or_no) {
1015 // cerr << "forced locate to " << ev->target_frame << endl;
1016 locate (ev->target_frame, false, true, false);
1018 // cerr << "soft locate to " << ev->target_frame << endl;
1019 start_locate (ev->target_frame, false, true, false);
1021 _send_timecode_update = true;
1024 case SessionEvent::LocateRoll:
1025 if (ev->yes_or_no) {
1026 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1027 locate (ev->target_frame, true, true, false);
1029 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1030 start_locate (ev->target_frame, true, true, false);
1032 _send_timecode_update = true;
1035 case SessionEvent::LocateRollLocate:
1036 // locate is handled by ::request_roll_at_and_return()
1037 _requested_return_frame = ev->target_frame;
1038 request_locate (ev->target2_frame, true);
1042 case SessionEvent::SetTransportSpeed:
1043 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1046 case SessionEvent::PunchIn:
1047 // cerr << "PunchIN at " << transport_frame() << endl;
1048 if (config.get_punch_in() && record_status() == Enabled) {
1055 case SessionEvent::PunchOut:
1056 // cerr << "PunchOUT at " << transport_frame() << endl;
1057 if (config.get_punch_out()) {
1058 step_back_from_record ();
1064 case SessionEvent::StopOnce:
1065 if (!non_realtime_work_pending()) {
1066 stop_transport (ev->yes_or_no);
1067 _clear_event_type (SessionEvent::StopOnce);
1073 case SessionEvent::RangeStop:
1074 if (!non_realtime_work_pending()) {
1075 stop_transport (ev->yes_or_no);
1081 case SessionEvent::RangeLocate:
1082 start_locate (ev->target_frame, true, true, false);
1087 case SessionEvent::Overwrite:
1088 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1091 case SessionEvent::SetTrackSpeed:
1092 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1095 case SessionEvent::SetSyncSource:
1096 use_sync_source (ev->slave);
1099 case SessionEvent::Audition:
1100 set_audition (ev->region);
1101 // drop reference to region
1102 ev->region.reset ();
1105 case SessionEvent::InputConfigurationChange:
1106 add_post_transport_work (PostTransportInputChange);
1107 _butler->schedule_transport_work ();
1110 case SessionEvent::SetPlayAudioRange:
1111 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1114 case SessionEvent::RealTimeOperation:
1116 del = false; // other side of RT request needs to clean up
1119 case SessionEvent::AdjustPlaybackBuffering:
1120 schedule_playback_buffering_adjustment ();
1123 case SessionEvent::AdjustCaptureBuffering:
1124 schedule_capture_buffering_adjustment ();
1127 case SessionEvent::SetTimecodeTransmission:
1128 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1132 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1138 del = del && !_remove_event (ev);
1147 Session::compute_stop_limit () const
1149 if (!Config->get_stop_at_session_end ()) {
1150 return max_framepos;
1153 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1154 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1156 if (actively_recording ()) {
1157 /* permanently recording */
1158 return max_framepos;
1159 } else if (punching_in && !punching_out) {
1160 /* punching in but never out */
1161 return max_framepos;
1162 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_frame()) {
1163 /* punching in and punching out after session end */
1164 return max_framepos;
1167 return current_end_frame ();