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/threads.h>
30 #include "ardour/audioengine.h"
31 #include "ardour/auditioner.h"
32 #include "ardour/butler.h"
33 #include "ardour/cycle_timer.h"
34 #include "ardour/debug.h"
35 #include "ardour/graph.h"
36 #include "ardour/port.h"
37 #include "ardour/process_thread.h"
38 #include "ardour/scene_changer.h"
39 #include "ardour/session.h"
40 #include "ardour/slave.h"
41 #include "ardour/ticker.h"
42 #include "ardour/types.h"
44 #include "midi++/mmc.h"
48 using namespace ARDOUR;
52 /** Called by the audio engine when there is work to be done with JACK.
53 * @param nframes Number of frames to process.
57 Session::process (pframes_t nframes)
59 framepos_t transport_at_start = _transport_frame;
63 if (processing_blocked()) {
68 if (non_realtime_work_pending()) {
69 if (!_butler->transport_work_requested ()) {
74 _engine.main_thread()->get_buffers ();
76 (this->*process_function) (nframes);
78 _engine.main_thread()->drop_buffers ();
80 /* deliver MIDI clock. Note that we need to use the transport frame
81 * position at the start of process(), not the value at the end of
82 * it. We may already have ticked() because of a transport state
83 * change, for example.
87 if (!_silent && !_engine.freewheeling() && Config->get_send_midi_clock() && (transport_speed() == 1.0f || transport_speed() == 0.0f) && midi_clock->has_midi_port()) {
88 midi_clock->tick (transport_at_start, nframes);
91 _scene_changer->run (transport_at_start, transport_at_start + nframes);
94 /* don't bother with a message */
97 SendFeedback (); /* EMIT SIGNAL */
101 Session::fail_roll (pframes_t nframes)
103 return no_roll (nframes);
107 Session::no_roll (pframes_t nframes)
111 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
113 int declick = get_transport_declick_required();
114 boost::shared_ptr<RouteList> r = routes.reader ();
117 _click_io->silence (nframes);
120 ltc_tx_send_time_code_for_cycle (_transport_frame, end_frame, _target_transport_speed, _transport_speed, 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_auditioner()) {
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 const framepos_t start_frame = _transport_frame;
158 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
160 if (_process_graph) {
161 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
162 _process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler);
165 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
169 if ((*i)->is_auditioner()) {
173 (*i)->set_pending_declick (declick);
177 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, b)) < 0) {
191 /** @param need_butler to be set to true by this method if it needs the butler,
192 * otherwise it must be left alone.
195 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
197 boost::shared_ptr<RouteList> r = routes.reader ();
199 const framepos_t start_frame = _transport_frame;
200 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
202 if (_process_graph) {
203 _process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
205 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
209 if ((*i)->is_auditioner()) {
215 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, b)) < 0) {
230 Session::get_track_statistics ()
235 boost::shared_ptr<RouteList> rl = routes.reader();
236 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
238 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
240 if (!tr || tr->hidden()) {
244 pworst = min (pworst, tr->playback_buffer_load());
245 cworst = min (cworst, tr->capture_buffer_load());
248 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
249 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
251 if (cworst < 0.4 || pworst < 0.4) {
253 g_get_current_time (&now);
254 std::cerr << g_time_val_to_iso8601 (&now) << " *** WARNING *** CAPTURE BUFFERS (WORST): " << cworst << "PLAYBACK BUFFERS (WORST): " << pworst << endl;
257 if (actively_recording()) {
262 /** Process callback used when the auditioner is not active */
264 Session::process_with_events (pframes_t nframes)
269 pframes_t this_nframes;
270 framepos_t end_frame;
271 bool session_needs_butler = false;
272 framecnt_t frames_moved;
274 /* make sure the auditioner is silent */
277 auditioner->silence (nframes);
280 /* handle any pending events */
282 while (pending_events.read (&ev, 1) == 1) {
286 /* if we are not in the middle of a state change,
287 and there are immediate events queued up,
291 while (!non_realtime_work_pending() && !immediate_events.empty()) {
292 SessionEvent *ev = immediate_events.front ();
293 immediate_events.pop_front ();
297 /* Decide on what to do with quarter-frame MTC during this cycle */
299 bool const was_sending_qf_mtc = _send_qf_mtc;
300 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
302 if (_transport_speed != 0) {
304 Config->get_send_mtc () &&
305 _transport_speed >= (1 - tolerance) &&
306 _transport_speed <= (1 + tolerance)
309 if (_send_qf_mtc && !was_sending_qf_mtc) {
310 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
311 _send_timecode_update = true;
314 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
315 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
316 a quarter of a second since we sent anything at all, so send a full MTC update
319 _send_timecode_update = true;
322 _pframes_since_last_mtc += nframes;
325 /* Events caused a transport change (or we re-started sending
326 * MTC), so send an MTC Full Frame (Timecode) message. This
327 * is sent whether rolling or not, to give slaves an idea of
328 * ardour time on locates (and allow slow slaves to position
329 * and prepare for rolling)
331 if (_send_timecode_update) {
332 send_full_time_code (_transport_frame, nframes);
335 if (!process_can_proceed()) {
340 if (events.empty() || next_event == events.end()) {
341 process_without_events (nframes);
345 if (_transport_speed == 1.0) {
346 frames_moved = (framecnt_t) nframes;
348 interpolation.set_target_speed (_target_transport_speed);
349 interpolation.set_speed (_transport_speed);
350 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
353 end_frame = _transport_frame + frames_moved;
356 SessionEvent* this_event;
357 Events::iterator the_next_one;
359 if (!process_can_proceed()) {
364 if (!_exporting && _slave) {
365 if (!follow_slave (nframes)) {
370 if (_transport_speed == 0) {
375 if (!_exporting && !timecode_transmission_suspended()) {
376 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
379 framepos_t stop_limit = compute_stop_limit ();
381 if (maybe_stop (stop_limit)) {
386 this_event = *next_event;
387 the_next_one = next_event;
390 /* yes folks, here it is, the actual loop where we really truly
396 this_nframes = nframes; /* real (jack) time relative */
397 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
399 /* running an event, position transport precisely to its time */
400 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
401 /* this isn't quite right for reverse play */
402 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
403 this_nframes = abs (floor(frames_moved / _transport_speed));
408 click (_transport_frame, this_nframes);
410 if (process_routes (this_nframes, session_needs_butler)) {
415 get_track_statistics ();
417 nframes -= this_nframes;
419 if (frames_moved < 0) {
420 decrement_transport_position (-frames_moved);
422 increment_transport_position (frames_moved);
425 maybe_stop (stop_limit);
426 check_declick_out ();
430 _engine.split_cycle (this_nframes);
433 /* now handle this event and all others scheduled for the same time */
435 while (this_event && this_event->action_frame == _transport_frame) {
436 process_event (this_event);
438 if (the_next_one == events.end()) {
441 this_event = *the_next_one;
446 /* if an event left our state changing, do the right thing */
448 if (nframes && non_realtime_work_pending()) {
453 /* this is necessary to handle the case of seamless looping */
454 end_frame = _transport_frame + floor (nframes * _transport_speed);
459 } /* implicit release of route lock */
461 if (session_needs_butler) {
467 Session::reset_slave_state ()
469 average_slave_delta = 1800;
470 delta_accumulator_cnt = 0;
471 have_first_delta_accumulator = false;
472 _slave_state = Stopped;
476 Session::transport_locked () const
480 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
488 Session::follow_slave (pframes_t nframes)
491 framepos_t slave_transport_frame;
492 framecnt_t this_delta;
497 config.set_external_sync (false);
501 _slave->speed_and_position (slave_speed, slave_transport_frame);
503 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
505 if (!_slave->locked()) {
506 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
510 if (slave_transport_frame > _transport_frame) {
511 this_delta = slave_transport_frame - _transport_frame;
514 this_delta = _transport_frame - slave_transport_frame;
518 if (_slave->starting()) {
522 if (_slave->is_always_synced() ||
523 (Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
526 /* if the TC source is synced, then we assume that its
527 speed is binary: 0.0 or 1.0
530 if (slave_speed != 0.0f) {
536 /* if we are chasing and the average delta between us and the
537 master gets too big, we want to switch to silent
538 motion. so keep track of that here.
541 if (_slave_state == Running) {
542 calculate_moving_average_of_slave_delta(dir, this_delta);
546 track_slave_state (slave_speed, slave_transport_frame, this_delta);
548 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
549 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
552 if (_slave_state == Running && !_slave->is_always_synced() &&
553 !(Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
556 if (_transport_speed != 0.0f) {
559 note that average_dir is +1 or -1
564 if (average_slave_delta == 0) {
568 delta = average_slave_delta;
569 delta *= average_dir;
573 if (slave_speed != 0.0) {
574 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
575 (int) (dir * this_delta),
579 slave_transport_frame,
580 average_slave_delta));
584 if (_slave->give_slave_full_control_over_transport_speed()) {
585 set_transport_speed (slave_speed, 0, false, false);
586 //std::cout << "set speed = " << slave_speed << "\n";
588 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
589 request_transport_speed (adjusted_speed);
590 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
591 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
596 if (!actively_recording() && (framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
597 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
605 if (_slave_state == Running && !non_realtime_work_pending()) {
606 /* speed is set, we're locked, and good to go */
611 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
612 follow_slave_silently (nframes, slave_speed);
615 /* don't move at all */
616 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
622 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
624 if (delta_accumulator_cnt >= delta_accumulator_size) {
625 have_first_delta_accumulator = true;
626 delta_accumulator_cnt = 0;
629 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
630 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
633 if (have_first_delta_accumulator) {
634 average_slave_delta = 0L;
635 for (int i = 0; i < delta_accumulator_size; ++i) {
636 average_slave_delta += delta_accumulator[i];
638 average_slave_delta /= (int32_t) delta_accumulator_size;
639 if (average_slave_delta < 0L) {
641 average_slave_delta = abs(average_slave_delta);
649 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t /*this_delta*/)
651 if (slave_speed != 0.0f) {
653 /* slave is running */
655 switch (_slave_state) {
657 if (_slave->requires_seekahead()) {
658 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
659 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
660 /* we can call locate() here because we are in process context */
661 locate (slave_wait_end, false, false);
662 _slave_state = Waiting;
666 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped -> running at %1\n", slave_transport_frame));
668 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
669 average_slave_delta = 0L;
671 Location* al = _locations->auto_loop_location();
673 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
675 request_play_loop(false);
678 if (slave_transport_frame != _transport_frame) {
679 DEBUG_TRACE (DEBUG::Slave, string_compose ("require locate to run. eng: %1 -> sl: %2\n", _transport_frame, slave_transport_frame));
680 locate (slave_transport_frame, false, false);
682 _slave_state = Running;
691 if (_slave_state == Waiting) {
693 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
695 if (slave_transport_frame >= slave_wait_end) {
697 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
699 _slave_state = Running;
701 /* now perform a "micro-seek" within the disk buffers to realign ourselves
702 precisely with the master.
707 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
709 boost::shared_ptr<RouteList> rl = routes.reader();
710 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
711 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
712 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
719 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
720 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
722 tr->internal_playback_seek (frame_delta);
725 _transport_frame += frame_delta;
728 cerr << "cannot micro-seek\n";
734 if (_slave_state == Running && _transport_speed == 0.0f) {
735 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
739 } else { // slave_speed is 0
741 /* slave has stopped */
743 if (_transport_speed != 0.0f) {
744 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
748 if (slave_transport_frame != _transport_frame) {
749 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
750 force_locate (slave_transport_frame, false);
758 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
760 if (slave_speed && _transport_speed) {
762 /* something isn't right, but we should move with the master
766 bool need_butler = false;
768 silent_process_routes (nframes, need_butler);
770 get_track_statistics ();
776 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
778 if (frames_moved < 0) {
779 decrement_transport_position (-frames_moved);
781 increment_transport_position (frames_moved);
784 framepos_t const stop_limit = compute_stop_limit ();
785 maybe_stop (stop_limit);
790 Session::process_without_events (pframes_t nframes)
792 bool session_needs_butler = false;
793 framecnt_t frames_moved;
795 if (!process_can_proceed()) {
800 if (!_exporting && _slave) {
801 if (!follow_slave (nframes)) {
802 ltc_tx_send_time_code_for_cycle (_transport_frame, _transport_frame, 0, 0 , nframes);
807 if (_transport_speed == 0) {
812 if (_transport_speed == 1.0) {
813 frames_moved = (framecnt_t) nframes;
815 interpolation.set_target_speed (_target_transport_speed);
816 interpolation.set_speed (_transport_speed);
817 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
820 if (!_exporting && !timecode_transmission_suspended()) {
821 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
824 ltc_tx_send_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, _target_transport_speed, _transport_speed, nframes);
826 framepos_t const stop_limit = compute_stop_limit ();
828 if (maybe_stop (stop_limit)) {
833 if (maybe_sync_start (nframes)) {
837 click (_transport_frame, nframes);
839 if (process_routes (nframes, session_needs_butler)) {
844 get_track_statistics ();
846 if (frames_moved < 0) {
847 decrement_transport_position (-frames_moved);
849 increment_transport_position (frames_moved);
852 maybe_stop (stop_limit);
853 check_declick_out ();
855 if (session_needs_butler) {
860 /** Process callback used when the auditioner is active.
861 * @param nframes number of frames to process.
864 Session::process_audition (pframes_t nframes)
867 boost::shared_ptr<RouteList> r = routes.reader ();
869 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
870 if (!(*i)->is_auditioner()) {
871 (*i)->silence (nframes);
875 /* run the auditioner, and if it says we need butler service, ask for it */
877 if (auditioner->play_audition (nframes) > 0) {
881 /* if using a monitor section, run it because otherwise we don't hear anything */
883 if (_monitor_out && auditioner->needs_monitor()) {
884 _monitor_out->monitor_run (_transport_frame, _transport_frame + nframes, nframes, false);
887 /* handle pending events */
889 while (pending_events.read (&ev, 1) == 1) {
893 /* if we are not in the middle of a state change,
894 and there are immediate events queued up,
898 while (!non_realtime_work_pending() && !immediate_events.empty()) {
899 SessionEvent *ev = immediate_events.front ();
900 immediate_events.pop_front ();
904 if (!auditioner->auditioning()) {
905 /* auditioner no longer active, so go back to the normal process callback */
906 process_function = &Session::process_with_events;
911 Session::maybe_sync_start (pframes_t & nframes)
913 pframes_t sync_offset;
915 if (!waiting_for_sync_offset) {
919 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
921 /* generate silence up to the sync point, then
922 adjust nframes + offset to reflect whatever
926 no_roll (sync_offset);
927 nframes -= sync_offset;
928 Port::increment_global_port_buffer_offset (sync_offset);
929 waiting_for_sync_offset = false;
932 return true; // done, nothing left to process
937 /* sync offset point is not within this process()
938 cycle, so just generate silence. and don't bother
939 with any fancy stuff here, just the minimal silence.
944 if (Config->get_locate_while_waiting_for_sync()) {
945 if (micro_locate (nframes)) {
946 /* XXX ERROR !!! XXX */
950 return true; // done, nothing left to process
957 Session::queue_event (SessionEvent* ev)
959 if (_state_of_the_state & Deletion) {
961 } else if (_state_of_the_state & Loading) {
964 pending_events.write (&ev, 1);
969 Session::set_next_event ()
971 if (events.empty()) {
972 next_event = events.end();
976 if (next_event == events.end()) {
977 next_event = events.begin();
980 if ((*next_event)->action_frame > _transport_frame) {
981 next_event = events.begin();
984 for (; next_event != events.end(); ++next_event) {
985 if ((*next_event)->action_frame >= _transport_frame) {
992 Session::process_event (SessionEvent* ev)
997 /* if we're in the middle of a state change (i.e. waiting
998 for the butler thread to complete the non-realtime
999 part of the change), we'll just have to queue this
1000 event for a time when the change is complete.
1003 if (non_realtime_work_pending()) {
1005 /* except locates, which we have the capability to handle */
1007 if (ev->type != SessionEvent::Locate) {
1008 immediate_events.insert (immediate_events.end(), ev);
1014 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1017 case SessionEvent::SetLoop:
1018 set_play_loop (ev->yes_or_no, ev->speed);
1021 case SessionEvent::AutoLoop:
1023 /* roll after locate, do not flush, set "with loop"
1024 true only if we are seamless looping
1026 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1032 case SessionEvent::AutoLoopDeclick:
1034 /* Request a declick fade-out and a fade-in; the fade-out will happen
1035 at the end of the loop, and the fade-in at the start.
1037 transport_sub_state |= (PendingLoopDeclickOut | PendingLoopDeclickIn);
1043 case SessionEvent::Locate:
1044 if (ev->yes_or_no) {
1045 /* args: do not roll after locate, do flush, not with loop */
1046 locate (ev->target_frame, false, true, false);
1048 /* args: do not roll after locate, do flush, not with loop */
1049 start_locate (ev->target_frame, false, true, false);
1051 _send_timecode_update = true;
1054 case SessionEvent::LocateRoll:
1055 if (ev->yes_or_no) {
1056 /* args: roll after locate, do flush, not with loop */
1057 locate (ev->target_frame, true, true, false);
1059 /* args: roll after locate, do flush, not with loop */
1060 start_locate (ev->target_frame, true, true, false);
1062 _send_timecode_update = true;
1065 case SessionEvent::Skip:
1066 if (Config->get_skip_playback()) {
1067 start_locate (ev->target_frame, true, true, false);
1068 _send_timecode_update = true;
1074 case SessionEvent::LocateRollLocate:
1075 // locate is handled by ::request_roll_at_and_return()
1076 _requested_return_frame = ev->target_frame;
1077 request_locate (ev->target2_frame, true);
1081 case SessionEvent::SetTransportSpeed:
1082 set_transport_speed (ev->speed, ev->target_frame, ev->yes_or_no, ev->second_yes_or_no, ev->third_yes_or_no);
1085 case SessionEvent::PunchIn:
1086 // cerr << "PunchIN at " << transport_frame() << endl;
1087 if (config.get_punch_in() && record_status() == Enabled) {
1094 case SessionEvent::PunchOut:
1095 // cerr << "PunchOUT at " << transport_frame() << endl;
1096 if (config.get_punch_out()) {
1097 step_back_from_record ();
1103 case SessionEvent::StopOnce:
1104 if (!non_realtime_work_pending()) {
1105 _clear_event_type (SessionEvent::StopOnce);
1106 stop_transport (ev->yes_or_no);
1112 case SessionEvent::RangeStop:
1113 if (!non_realtime_work_pending()) {
1114 stop_transport (ev->yes_or_no);
1120 case SessionEvent::RangeLocate:
1121 /* args: roll after locate, do flush, not with loop */
1122 start_locate (ev->target_frame, true, true, false);
1127 case SessionEvent::Overwrite:
1128 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1131 case SessionEvent::SetTrackSpeed:
1132 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1135 case SessionEvent::SetSyncSource:
1136 DEBUG_TRACE (DEBUG::Slave, "seen request for new slave\n");
1137 use_sync_source (ev->slave);
1140 case SessionEvent::Audition:
1141 set_audition (ev->region);
1142 // drop reference to region
1143 ev->region.reset ();
1146 case SessionEvent::InputConfigurationChange:
1147 add_post_transport_work (PostTransportInputChange);
1148 _butler->schedule_transport_work ();
1151 case SessionEvent::SetPlayAudioRange:
1152 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1155 case SessionEvent::CancelPlayAudioRange:
1159 case SessionEvent::RealTimeOperation:
1161 del = false; // other side of RT request needs to clean up
1164 case SessionEvent::AdjustPlaybackBuffering:
1165 schedule_playback_buffering_adjustment ();
1168 case SessionEvent::AdjustCaptureBuffering:
1169 schedule_capture_buffering_adjustment ();
1172 case SessionEvent::SetTimecodeTransmission:
1173 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1177 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1178 abort(); /*NOTREACHED*/
1183 del = del && !_remove_event (ev);
1192 Session::compute_stop_limit () const
1194 if (!Config->get_stop_at_session_end ()) {
1195 return max_framepos;
1199 return max_framepos;
1203 bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1204 bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1206 if (actively_recording ()) {
1207 /* permanently recording */
1208 return max_framepos;
1209 } else if (punching_in && !punching_out) {
1210 /* punching in but never out */
1211 return max_framepos;
1212 } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_frame()) {
1213 /* punching in and punching out after session end */
1214 return max_framepos;
1217 return current_end_frame ();