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 using namespace ARDOUR;
54 /** Called by the audio engine when there is work to be done with JACK.
55 * @param nframes Number of frames to process.
59 Session::process (pframes_t nframes)
61 framepos_t transport_at_start = _transport_frame;
63 MIDI::Manager::instance()->cycle_start(nframes);
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 (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 */
100 MIDI::Manager::instance()->cycle_end();
104 Session::fail_roll (pframes_t nframes)
106 return no_roll (nframes);
110 Session::no_roll (pframes_t nframes)
114 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
116 bool declick = get_transport_declick_required();
117 boost::shared_ptr<RouteList> r = routes.reader ();
120 _click_io->silence (nframes);
123 if (_process_graph) {
124 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
125 _process_graph->routes_no_roll( nframes, _transport_frame, end_frame, non_realtime_work_pending(), declick);
127 PT_TIMING_CHECK (10);
128 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
130 if ((*i)->is_hidden()) {
134 (*i)->set_pending_declick (declick);
136 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending())) {
137 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
142 PT_TIMING_CHECK (11);
150 Session::process_routes (pframes_t nframes, bool& need_butler)
152 int declick = get_transport_declick_required();
153 boost::shared_ptr<RouteList> r = routes.reader ();
155 if (transport_sub_state & StopPendingCapture) {
156 /* force a declick out */
160 const framepos_t start_frame = _transport_frame;
161 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
163 if (_process_graph) {
164 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
165 _process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);
168 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
172 if ((*i)->is_hidden()) {
176 (*i)->set_pending_declick (declick);
178 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, need_butler)) < 0) {
189 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
191 boost::shared_ptr<RouteList> r = routes.reader ();
193 const framepos_t start_frame = _transport_frame;
194 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
196 if (_process_graph) {
197 _process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
199 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
203 if ((*i)->is_hidden()) {
207 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, need_butler)) < 0) {
218 Session::get_track_statistics ()
223 boost::shared_ptr<RouteList> rl = routes.reader();
224 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
226 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
228 if (!tr || tr->hidden()) {
232 pworst = min (pworst, tr->playback_buffer_load());
233 cworst = min (cworst, tr->capture_buffer_load());
236 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
237 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
239 if (actively_recording()) {
244 /** Process callback used when the auditioner is not active */
246 Session::process_with_events (pframes_t nframes)
251 pframes_t this_nframes;
252 framepos_t end_frame;
253 bool session_needs_butler = false;
254 framecnt_t frames_moved;
256 /* make sure the auditioner is silent */
259 auditioner->silence (nframes);
262 /* handle any pending events */
264 while (pending_events.read (&ev, 1) == 1) {
268 /* if we are not in the middle of a state change,
269 and there are immediate events queued up,
273 while (!non_realtime_work_pending() && !immediate_events.empty()) {
274 SessionEvent *ev = immediate_events.front ();
275 immediate_events.pop_front ();
279 /* Decide on what to do with quarter-frame MTC during this cycle */
281 bool const was_sending_qf_mtc = _send_qf_mtc;
282 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
284 if (_transport_speed != 0) {
286 Config->get_send_mtc () &&
287 _transport_speed >= (1 - tolerance) &&
288 _transport_speed <= (1 + tolerance)
291 if (_send_qf_mtc && !was_sending_qf_mtc) {
292 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
293 _send_timecode_update = true;
296 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
297 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
298 a quarter of a second since we sent anything at all, so send a full MTC update
301 _send_timecode_update = true;
304 _pframes_since_last_mtc += nframes;
307 /* Events caused a transport change (or we re-started sending
308 * MTC), so send an MTC Full Frame (Timecode) message. This
309 * is sent whether rolling or not, to give slaves an idea of
310 * ardour time on locates (and allow slow slaves to position
311 * and prepare for rolling)
313 if (_send_timecode_update) {
314 send_full_time_code (_transport_frame);
317 if (!process_can_proceed()) {
322 if (events.empty() || next_event == events.end()) {
323 process_without_events (nframes);
327 if (_transport_speed == 1.0) {
328 frames_moved = (framecnt_t) nframes;
330 interpolation.set_target_speed (fabs(_target_transport_speed));
331 interpolation.set_speed (fabs(_transport_speed));
332 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
335 end_frame = _transport_frame + frames_moved;
338 SessionEvent* this_event;
339 Events::iterator the_next_one;
341 if (!process_can_proceed()) {
346 if (!_exporting && _slave) {
347 if (!follow_slave (nframes)) {
352 if (_transport_speed == 0) {
357 if (!_exporting && !timecode_transmission_suspended()) {
358 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
361 framepos_t stop_limit = compute_stop_limit ();
363 if (maybe_stop (stop_limit)) {
368 this_event = *next_event;
369 the_next_one = next_event;
372 /* yes folks, here it is, the actual loop where we really truly
378 this_nframes = nframes; /* real (jack) time relative */
379 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
381 /* running an event, position transport precisely to its time */
382 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
383 /* this isn't quite right for reverse play */
384 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
385 this_nframes = abs (floor(frames_moved / _transport_speed));
390 click (_transport_frame, this_nframes);
392 if (process_routes (this_nframes, session_needs_butler)) {
397 get_track_statistics ();
399 nframes -= this_nframes;
401 if (frames_moved < 0) {
402 decrement_transport_position (-frames_moved);
404 increment_transport_position (frames_moved);
407 maybe_stop (stop_limit);
408 check_declick_out ();
411 _engine.split_cycle (this_nframes);
413 /* now handle this event and all others scheduled for the same time */
415 while (this_event && this_event->action_frame == _transport_frame) {
416 process_event (this_event);
418 if (the_next_one == events.end()) {
421 this_event = *the_next_one;
426 /* if an event left our state changing, do the right thing */
428 if (nframes && non_realtime_work_pending()) {
433 /* this is necessary to handle the case of seamless looping */
434 end_frame = _transport_frame + floor (nframes * _transport_speed);
439 } /* implicit release of route lock */
441 if (session_needs_butler) {
447 Session::reset_slave_state ()
449 average_slave_delta = 1800;
450 delta_accumulator_cnt = 0;
451 have_first_delta_accumulator = false;
452 _slave_state = Stopped;
456 Session::transport_locked () const
460 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
468 Session::follow_slave (pframes_t nframes)
471 framepos_t slave_transport_frame;
472 framecnt_t this_delta;
477 config.set_external_sync (false);
481 _slave->speed_and_position (slave_speed, slave_transport_frame);
483 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
485 if (!_slave->locked()) {
486 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
490 if (slave_transport_frame > _transport_frame) {
491 this_delta = slave_transport_frame - _transport_frame;
494 this_delta = _transport_frame - slave_transport_frame;
498 if (_slave->starting()) {
502 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
504 /* if the TC source is synced, then we assume that its
505 speed is binary: 0.0 or 1.0
508 if (slave_speed != 0.0f) {
514 /* if we are chasing and the average delta between us and the
515 master gets too big, we want to switch to silent
516 motion. so keep track of that here.
519 if (_slave_state == Running) {
520 calculate_moving_average_of_slave_delta(dir, this_delta);
524 track_slave_state (slave_speed, slave_transport_frame, this_delta);
526 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
527 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
530 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
532 if (_transport_speed != 0.0f) {
535 note that average_dir is +1 or -1
540 if (average_slave_delta == 0) {
544 delta = average_slave_delta;
545 delta *= average_dir;
549 if (slave_speed != 0.0) {
550 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
551 (int) (dir * this_delta),
555 slave_transport_frame,
556 average_slave_delta));
560 if (_slave->give_slave_full_control_over_transport_speed()) {
561 set_transport_speed (slave_speed, false, false);
562 //std::cout << "set speed = " << slave_speed << "\n";
564 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
565 request_transport_speed (adjusted_speed);
566 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
567 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
572 if ((framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
573 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
581 if (_slave_state == Running && !non_realtime_work_pending()) {
582 /* speed is set, we're locked, and good to go */
587 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
588 follow_slave_silently (nframes, slave_speed);
591 /* don't move at all */
592 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
598 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
600 if (delta_accumulator_cnt >= delta_accumulator_size) {
601 have_first_delta_accumulator = true;
602 delta_accumulator_cnt = 0;
605 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
606 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
609 if (have_first_delta_accumulator) {
610 average_slave_delta = 0L;
611 for (int i = 0; i < delta_accumulator_size; ++i) {
612 average_slave_delta += delta_accumulator[i];
614 average_slave_delta /= (int32_t) delta_accumulator_size;
615 if (average_slave_delta < 0L) {
617 average_slave_delta = abs(average_slave_delta);
625 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t /*this_delta*/)
627 if (slave_speed != 0.0f) {
629 /* slave is running */
631 switch (_slave_state) {
633 if (_slave->requires_seekahead()) {
634 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
635 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
636 /* we can call locate() here because we are in process context */
637 locate (slave_wait_end, false, false);
638 _slave_state = Waiting;
642 _slave_state = Running;
644 Location* al = _locations->auto_loop_location();
646 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
648 request_play_loop(false);
651 if (slave_transport_frame != _transport_frame) {
652 locate (slave_transport_frame, false, false);
662 if (_slave_state == Waiting) {
664 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
666 if (slave_transport_frame >= slave_wait_end) {
668 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
670 _slave_state = Running;
672 /* now perform a "micro-seek" within the disk buffers to realign ourselves
673 precisely with the master.
678 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
680 boost::shared_ptr<RouteList> rl = routes.reader();
681 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
682 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
683 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
690 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
691 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
693 tr->internal_playback_seek (frame_delta);
696 _transport_frame += frame_delta;
699 cerr << "cannot micro-seek\n";
703 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
704 average_slave_delta = 0L;
708 if (_slave_state == Running && _transport_speed == 0.0f) {
709 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
713 } else { // slave_speed is 0
715 /* slave has stopped */
717 if (_transport_speed != 0.0f) {
718 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
722 if (slave_transport_frame != _transport_frame) {
723 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
724 force_locate (slave_transport_frame, false);
727 _slave_state = Stopped;
732 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
734 if (slave_speed && _transport_speed) {
736 /* something isn't right, but we should move with the master
742 silent_process_routes (nframes, need_butler);
744 get_track_statistics ();
750 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
752 if (frames_moved < 0) {
753 decrement_transport_position (-frames_moved);
755 increment_transport_position (frames_moved);
758 framepos_t const stop_limit = compute_stop_limit ();
759 maybe_stop (stop_limit);
764 Session::process_without_events (pframes_t nframes)
766 bool session_needs_butler = false;
767 framecnt_t frames_moved;
769 if (!process_can_proceed()) {
774 if (!_exporting && _slave) {
775 if (!follow_slave (nframes)) {
780 if (_transport_speed == 0) {
785 if (_transport_speed == 1.0) {
786 frames_moved = (framecnt_t) nframes;
788 interpolation.set_target_speed (fabs(_target_transport_speed));
789 interpolation.set_speed (fabs(_transport_speed));
790 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
793 if (!_exporting && !timecode_transmission_suspended()) {
794 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
797 framepos_t const stop_limit = compute_stop_limit ();
799 if (maybe_stop (stop_limit)) {
804 if (maybe_sync_start (nframes)) {
808 click (_transport_frame, nframes);
810 if (process_routes (nframes, session_needs_butler)) {
815 get_track_statistics ();
817 /* XXX: I'm not sure whether this is correct, but at least it
818 matches process_with_events, so that this new frames_moved
819 is -ve when transport speed is -ve. This means that the
820 transport position is updated correctly when we are in
821 reverse. It seems a bit wrong that we're not using the
822 interpolator to compute this.
825 frames_moved = (framecnt_t) floor (_transport_speed * nframes);
827 if (frames_moved < 0) {
828 decrement_transport_position (-frames_moved);
830 increment_transport_position (frames_moved);
833 maybe_stop (stop_limit);
834 check_declick_out ();
836 if (session_needs_butler) {
841 /** Process callback used when the auditioner is active.
842 * @param nframes number of frames to process.
845 Session::process_audition (pframes_t nframes)
848 boost::shared_ptr<RouteList> r = routes.reader ();
850 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
851 if (!(*i)->is_hidden()) {
852 (*i)->silence (nframes);
856 /* run the auditioner, and if it says we need butler service, ask for it */
858 if (auditioner->play_audition (nframes) > 0) {
862 /* if using a monitor section, run it because otherwise we don't hear anything */
864 if (auditioner->needs_monitor()) {
865 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
868 /* handle pending events */
870 while (pending_events.read (&ev, 1) == 1) {
874 /* if we are not in the middle of a state change,
875 and there are immediate events queued up,
879 while (!non_realtime_work_pending() && !immediate_events.empty()) {
880 SessionEvent *ev = immediate_events.front ();
881 immediate_events.pop_front ();
885 if (!auditioner->auditioning()) {
886 /* auditioner no longer active, so go back to the normal process callback */
887 process_function = &Session::process_with_events;
892 Session::maybe_sync_start (pframes_t & nframes)
894 pframes_t sync_offset;
896 if (!waiting_for_sync_offset) {
900 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
902 /* generate silence up to the sync point, then
903 adjust nframes + offset to reflect whatever
907 no_roll (sync_offset);
908 nframes -= sync_offset;
909 Port::increment_global_port_buffer_offset (sync_offset);
910 waiting_for_sync_offset = false;
913 return true; // done, nothing left to process
918 /* sync offset point is not within this process()
919 cycle, so just generate silence. and don't bother
920 with any fancy stuff here, just the minimal silence.
925 if (Config->get_locate_while_waiting_for_sync()) {
926 if (micro_locate (nframes)) {
927 /* XXX ERROR !!! XXX */
931 return true; // done, nothing left to process
938 Session::queue_event (SessionEvent* ev)
940 if (_state_of_the_state & Deletion) {
942 } else if (_state_of_the_state & Loading) {
945 pending_events.write (&ev, 1);
950 Session::set_next_event ()
952 if (events.empty()) {
953 next_event = events.end();
957 if (next_event == events.end()) {
958 next_event = events.begin();
961 if ((*next_event)->action_frame > _transport_frame) {
962 next_event = events.begin();
965 for (; next_event != events.end(); ++next_event) {
966 if ((*next_event)->action_frame >= _transport_frame) {
973 Session::process_event (SessionEvent* ev)
978 /* if we're in the middle of a state change (i.e. waiting
979 for the butler thread to complete the non-realtime
980 part of the change), we'll just have to queue this
981 event for a time when the change is complete.
984 if (non_realtime_work_pending()) {
986 /* except locates, which we have the capability to handle */
988 if (ev->type != SessionEvent::Locate) {
989 immediate_events.insert (immediate_events.end(), ev);
995 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
998 case SessionEvent::SetLoop:
999 set_play_loop (ev->yes_or_no);
1002 case SessionEvent::AutoLoop:
1004 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1010 case SessionEvent::Locate:
1011 if (ev->yes_or_no) {
1012 // cerr << "forced locate to " << ev->target_frame << endl;
1013 locate (ev->target_frame, false, true, false);
1015 // cerr << "soft locate to " << ev->target_frame << endl;
1016 start_locate (ev->target_frame, false, true, false);
1018 _send_timecode_update = true;
1021 case SessionEvent::LocateRoll:
1022 if (ev->yes_or_no) {
1023 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1024 locate (ev->target_frame, true, true, false);
1026 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1027 start_locate (ev->target_frame, true, true, false);
1029 _send_timecode_update = true;
1032 case SessionEvent::LocateRollLocate:
1033 // locate is handled by ::request_roll_at_and_return()
1034 _requested_return_frame = ev->target_frame;
1035 request_locate (ev->target2_frame, true);
1039 case SessionEvent::SetTransportSpeed:
1040 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1043 case SessionEvent::PunchIn:
1044 // cerr << "PunchIN at " << transport_frame() << endl;
1045 if (config.get_punch_in() && record_status() == Enabled) {
1052 case SessionEvent::PunchOut:
1053 // cerr << "PunchOUT at " << transport_frame() << endl;
1054 if (config.get_punch_out()) {
1055 step_back_from_record ();
1061 case SessionEvent::StopOnce:
1062 if (!non_realtime_work_pending()) {
1063 stop_transport (ev->yes_or_no);
1064 _clear_event_type (SessionEvent::StopOnce);
1070 case SessionEvent::RangeStop:
1071 if (!non_realtime_work_pending()) {
1072 stop_transport (ev->yes_or_no);
1078 case SessionEvent::RangeLocate:
1079 start_locate (ev->target_frame, true, true, false);
1084 case SessionEvent::Overwrite:
1085 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1088 case SessionEvent::SetTrackSpeed:
1089 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1092 case SessionEvent::SetSyncSource:
1093 use_sync_source (ev->slave);
1096 case SessionEvent::Audition:
1097 set_audition (ev->region);
1098 // drop reference to region
1099 ev->region.reset ();
1102 case SessionEvent::InputConfigurationChange:
1103 add_post_transport_work (PostTransportInputChange);
1104 _butler->schedule_transport_work ();
1107 case SessionEvent::SetPlayAudioRange:
1108 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1111 case SessionEvent::RealTimeOperation:
1113 del = false; // other side of RT request needs to clean up
1116 case SessionEvent::AdjustPlaybackBuffering:
1117 schedule_playback_buffering_adjustment ();
1120 case SessionEvent::AdjustCaptureBuffering:
1121 schedule_capture_buffering_adjustment ();
1124 case SessionEvent::SetTimecodeTransmission:
1125 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1129 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1135 del = del && !_remove_event (ev);
1144 Session::compute_stop_limit () const
1146 if (!Config->get_stop_at_session_end ()) {
1147 return max_framepos;
1150 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1151 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1153 if (actively_recording ()) {
1154 /* permanently recording */
1155 return max_framepos;
1156 } else if (punching_in && !punching_out) {
1157 /* punching in but never out */
1158 return max_framepos;
1159 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_frame()) {
1160 /* punching in and punching out after session end */
1161 return max_framepos;
1164 return current_end_frame ();