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 (route_graph->threads_in_use() > 0) {
111 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
112 route_graph->routes_no_roll( nframes, _transport_frame, end_frame, non_realtime_work_pending(), actively_recording(), 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 actively_recording())) {
124 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
135 Session::process_routes (pframes_t nframes, bool& need_butler)
138 int declick = get_transport_declick_required();
139 boost::shared_ptr<RouteList> r = routes.reader ();
141 if (transport_sub_state & StopPendingCapture) {
142 /* force a declick out */
146 record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
148 const framepos_t start_frame = _transport_frame;
149 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
151 /* XXX this is hack to force use of the graph even if we are only
152 using 1 thread. its needed because otherwise when we remove
153 tracks, the graph never gets updated.
155 if (1 || route_graph->threads_in_use() > 0) {
156 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
157 route_graph->process_routes (nframes, start_frame, end_frame, declick, record_active, need_butler);
160 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
164 if ((*i)->is_hidden()) {
168 (*i)->set_pending_declick (declick);
170 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, need_butler)) < 0) {
181 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
183 bool record_active = actively_recording();
184 boost::shared_ptr<RouteList> r = routes.reader ();
186 const framepos_t start_frame = _transport_frame;
187 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
189 /* XXX this is hack to force use of the graph even if we are only
190 using 1 thread. its needed because otherwise when we remove
191 tracks, the graph never gets updated.
193 if (1 || route_graph->threads_in_use() > 0) {
194 route_graph->silent_process_routes (nframes, start_frame, end_frame, record_active, need_butler);
196 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
200 if ((*i)->is_hidden()) {
204 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, need_butler)) < 0) {
215 Session::get_track_statistics ()
220 boost::shared_ptr<RouteList> rl = routes.reader();
221 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
223 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
225 if (!tr || tr->hidden()) {
229 pworst = min (pworst, tr->playback_buffer_load());
230 cworst = min (cworst, tr->capture_buffer_load());
233 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
234 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
236 if (actively_recording()) {
241 /** Process callback used when the auditioner is not active */
243 Session::process_with_events (pframes_t nframes)
246 pframes_t this_nframes;
247 framepos_t end_frame;
248 bool session_needs_butler = false;
249 framecnt_t frames_moved;
251 /* make sure the auditioner is silent */
254 auditioner->silence (nframes);
257 /* handle any pending events */
259 while (pending_events.read (&ev, 1) == 1) {
263 /* if we are not in the middle of a state change,
264 and there are immediate events queued up,
268 while (!non_realtime_work_pending() && !immediate_events.empty()) {
269 SessionEvent *ev = immediate_events.front ();
270 immediate_events.pop_front ();
274 /* Decide on what to do with quarter-frame MTC during this cycle */
276 bool const was_sending_qf_mtc = _send_qf_mtc;
277 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
279 if (_transport_speed != 0) {
281 Config->get_send_mtc () &&
282 _transport_speed >= (1 - tolerance) &&
283 _transport_speed <= (1 + tolerance)
286 if (_send_qf_mtc && !was_sending_qf_mtc) {
287 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
288 _send_timecode_update = true;
291 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
292 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
293 a quarter of a second since we sent anything at all, so send a full MTC update
296 _send_timecode_update = true;
299 _pframes_since_last_mtc += nframes;
302 /* Events caused a transport change (or we re-started sending
303 * MTC), so send an MTC Full Frame (Timecode) message. This
304 * is sent whether rolling or not, to give slaves an idea of
305 * ardour time on locates (and allow slow slaves to position
306 * and prepare for rolling)
308 if (_send_timecode_update) {
309 send_full_time_code (_transport_frame);
312 if (!process_can_proceed()) {
317 if (events.empty() || next_event == events.end()) {
318 process_without_events (nframes);
322 if (_transport_speed == 1.0) {
323 frames_moved = (framecnt_t) nframes;
325 interpolation.set_target_speed (fabs(_target_transport_speed));
326 interpolation.set_speed (fabs(_transport_speed));
327 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
330 end_frame = _transport_frame + frames_moved;
333 SessionEvent* this_event;
334 Events::iterator the_next_one;
336 if (!process_can_proceed()) {
341 if (!_exporting && _slave) {
342 if (!follow_slave (nframes)) {
347 if (_transport_speed == 0) {
352 if (!_exporting && !timecode_transmission_suspended()) {
353 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
356 framepos_t stop_limit = compute_stop_limit ();
358 if (maybe_stop (stop_limit)) {
363 this_event = *next_event;
364 the_next_one = next_event;
367 /* yes folks, here it is, the actual loop where we really truly
373 this_nframes = nframes; /* real (jack) time relative */
374 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
376 /* running an event, position transport precisely to its time */
377 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
378 /* this isn't quite right for reverse play */
379 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
380 this_nframes = abs (floor(frames_moved / _transport_speed));
385 click (_transport_frame, this_nframes);
387 if (process_routes (this_nframes, session_needs_butler)) {
392 get_track_statistics ();
394 nframes -= this_nframes;
396 if (frames_moved < 0) {
397 decrement_transport_position (-frames_moved);
399 increment_transport_position (frames_moved);
402 maybe_stop (stop_limit);
403 check_declick_out ();
406 _engine.split_cycle (this_nframes);
408 /* now handle this event and all others scheduled for the same time */
410 while (this_event && this_event->action_frame == _transport_frame) {
411 process_event (this_event);
413 if (the_next_one == events.end()) {
416 this_event = *the_next_one;
421 /* if an event left our state changing, do the right thing */
423 if (nframes && non_realtime_work_pending()) {
428 /* this is necessary to handle the case of seamless looping */
429 end_frame = _transport_frame + floor (nframes * _transport_speed);
434 } /* implicit release of route lock */
436 if (session_needs_butler) {
442 Session::reset_slave_state ()
444 average_slave_delta = 1800;
445 delta_accumulator_cnt = 0;
446 have_first_delta_accumulator = false;
447 _slave_state = Stopped;
451 Session::transport_locked () const
455 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
463 Session::follow_slave (pframes_t nframes)
466 framepos_t slave_transport_frame;
467 framecnt_t this_delta;
472 config.set_external_sync (false);
476 _slave->speed_and_position (slave_speed, slave_transport_frame);
478 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
480 if (!_slave->locked()) {
481 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
485 if (slave_transport_frame > _transport_frame) {
486 this_delta = slave_transport_frame - _transport_frame;
489 this_delta = _transport_frame - slave_transport_frame;
493 if (_slave->starting()) {
497 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
499 /* if the TC source is synced, then we assume that its
500 speed is binary: 0.0 or 1.0
503 if (slave_speed != 0.0f) {
509 /* if we are chasing and the average delta between us and the
510 master gets too big, we want to switch to silent
511 motion. so keep track of that here.
514 if (_slave_state == Running) {
515 calculate_moving_average_of_slave_delta(dir, this_delta);
519 track_slave_state (slave_speed, slave_transport_frame, this_delta);
521 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
522 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
525 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
527 if (_transport_speed != 0.0f) {
530 note that average_dir is +1 or -1
535 if (average_slave_delta == 0) {
539 delta = average_slave_delta;
540 delta *= average_dir;
544 if (slave_speed != 0.0) {
545 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
546 (int) (dir * this_delta),
550 slave_transport_frame,
551 average_slave_delta));
555 if (_slave->give_slave_full_control_over_transport_speed()) {
556 set_transport_speed (slave_speed, false, false);
557 //std::cout << "set speed = " << slave_speed << "\n";
559 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
560 request_transport_speed (adjusted_speed);
561 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
562 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
567 if ((framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
568 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
576 if (_slave_state == Running && !non_realtime_work_pending()) {
577 /* speed is set, we're locked, and good to go */
582 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
583 follow_slave_silently (nframes, slave_speed);
586 /* don't move at all */
587 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
593 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
595 if (delta_accumulator_cnt >= delta_accumulator_size) {
596 have_first_delta_accumulator = true;
597 delta_accumulator_cnt = 0;
600 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
601 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
604 if (have_first_delta_accumulator) {
605 average_slave_delta = 0L;
606 for (int i = 0; i < delta_accumulator_size; ++i) {
607 average_slave_delta += delta_accumulator[i];
609 average_slave_delta /= (int32_t) delta_accumulator_size;
610 if (average_slave_delta < 0L) {
612 average_slave_delta = abs(average_slave_delta);
620 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t this_delta)
622 if (slave_speed != 0.0f) {
624 /* slave is running */
626 switch (_slave_state) {
628 if (_slave->requires_seekahead()) {
629 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
630 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
631 /* we can call locate() here because we are in process context */
632 locate (slave_wait_end, false, false);
633 _slave_state = Waiting;
637 _slave_state = Running;
639 Location* al = _locations->auto_loop_location();
641 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
643 request_play_loop(false);
646 if (slave_transport_frame != _transport_frame) {
647 locate (slave_transport_frame, false, false);
657 if (_slave_state == Waiting) {
659 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
661 if (slave_transport_frame >= slave_wait_end) {
663 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
665 _slave_state = Running;
667 /* now perform a "micro-seek" within the disk buffers to realign ourselves
668 precisely with the master.
673 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
675 boost::shared_ptr<RouteList> rl = routes.reader();
676 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
677 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
678 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
685 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
686 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
688 tr->internal_playback_seek (frame_delta);
691 _transport_frame += frame_delta;
694 cerr << "cannot micro-seek\n";
698 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
699 average_slave_delta = 0L;
703 if (_slave_state == Running && _transport_speed == 0.0f) {
704 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
708 } else { // slave_speed is 0
710 /* slave has stopped */
712 if (_transport_speed != 0.0f) {
713 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
717 if (slave_transport_frame != _transport_frame) {
718 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
719 force_locate (slave_transport_frame, false);
722 _slave_state = Stopped;
727 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
729 if (slave_speed && _transport_speed) {
731 /* something isn't right, but we should move with the master
737 silent_process_routes (nframes, need_butler);
739 get_track_statistics ();
745 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
747 if (frames_moved < 0) {
748 decrement_transport_position (-frames_moved);
750 increment_transport_position (frames_moved);
753 framepos_t const stop_limit = compute_stop_limit ();
754 maybe_stop (stop_limit);
759 Session::process_without_events (pframes_t nframes)
761 bool session_needs_butler = false;
762 framecnt_t frames_moved;
764 if (!process_can_proceed()) {
769 if (!_exporting && _slave) {
770 if (!follow_slave (nframes)) {
775 if (_transport_speed == 0) {
780 if (_transport_speed == 1.0) {
781 frames_moved = (framecnt_t) nframes;
783 interpolation.set_target_speed (fabs(_target_transport_speed));
784 interpolation.set_speed (fabs(_transport_speed));
785 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
788 if (!_exporting && !timecode_transmission_suspended()) {
789 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
792 framepos_t const stop_limit = compute_stop_limit ();
794 if (maybe_stop (stop_limit)) {
799 if (maybe_sync_start (nframes)) {
803 click (_transport_frame, nframes);
805 if (process_routes (nframes, session_needs_butler)) {
810 get_track_statistics ();
812 /* XXX: I'm not sure whether this is correct, but at least it
813 matches process_with_events, so that this new frames_moved
814 is -ve when transport speed is -ve. This means that the
815 transport position is updated correctly when we are in
816 reverse. It seems a bit wrong that we're not using the
817 interpolator to compute this.
820 frames_moved = (framecnt_t) floor (_transport_speed * nframes);
822 if (frames_moved < 0) {
823 decrement_transport_position (-frames_moved);
825 increment_transport_position (frames_moved);
828 maybe_stop (stop_limit);
829 check_declick_out ();
831 if (session_needs_butler) {
836 /** Process callback used when the auditioner is active.
837 * @param nframes number of frames to process.
840 Session::process_audition (pframes_t nframes)
843 boost::shared_ptr<RouteList> r = routes.reader ();
845 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
846 if (!(*i)->is_hidden()) {
847 (*i)->silence (nframes);
851 /* run the auditioner, and if it says we need butler service, ask for it */
853 if (auditioner->play_audition (nframes) > 0) {
857 /* if using a monitor section, run it because otherwise we don't hear anything */
859 if (auditioner->needs_monitor()) {
860 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
863 /* handle pending events */
865 while (pending_events.read (&ev, 1) == 1) {
869 /* if we are not in the middle of a state change,
870 and there are immediate events queued up,
874 while (!non_realtime_work_pending() && !immediate_events.empty()) {
875 SessionEvent *ev = immediate_events.front ();
876 immediate_events.pop_front ();
880 if (!auditioner->auditioning()) {
881 /* auditioner no longer active, so go back to the normal process callback */
882 process_function = &Session::process_with_events;
887 Session::maybe_sync_start (pframes_t & nframes)
889 pframes_t sync_offset;
891 if (!waiting_for_sync_offset) {
895 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
897 /* generate silence up to the sync point, then
898 adjust nframes + offset to reflect whatever
902 no_roll (sync_offset);
903 nframes -= sync_offset;
904 Port::increment_global_port_buffer_offset (sync_offset);
905 waiting_for_sync_offset = false;
908 return true; // done, nothing left to process
913 /* sync offset point is not within this process()
914 cycle, so just generate silence. and don't bother
915 with any fancy stuff here, just the minimal silence.
920 if (Config->get_locate_while_waiting_for_sync()) {
921 if (micro_locate (nframes)) {
922 /* XXX ERROR !!! XXX */
926 return true; // done, nothing left to process
933 Session::queue_event (SessionEvent* ev)
935 if (_state_of_the_state & Deletion) {
937 } else if (_state_of_the_state & Loading) {
940 pending_events.write (&ev, 1);
945 Session::set_next_event ()
947 if (events.empty()) {
948 next_event = events.end();
952 if (next_event == events.end()) {
953 next_event = events.begin();
956 if ((*next_event)->action_frame > _transport_frame) {
957 next_event = events.begin();
960 for (; next_event != events.end(); ++next_event) {
961 if ((*next_event)->action_frame >= _transport_frame) {
968 Session::process_event (SessionEvent* ev)
973 /* if we're in the middle of a state change (i.e. waiting
974 for the butler thread to complete the non-realtime
975 part of the change), we'll just have to queue this
976 event for a time when the change is complete.
979 if (non_realtime_work_pending()) {
981 /* except locates, which we have the capability to handle */
983 if (ev->type != SessionEvent::Locate) {
984 immediate_events.insert (immediate_events.end(), ev);
990 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
993 case SessionEvent::SetLoop:
994 set_play_loop (ev->yes_or_no);
997 case SessionEvent::AutoLoop:
999 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1005 case SessionEvent::Locate:
1006 if (ev->yes_or_no) {
1007 // cerr << "forced locate to " << ev->target_frame << endl;
1008 locate (ev->target_frame, false, true, false);
1010 // cerr << "soft locate to " << ev->target_frame << endl;
1011 start_locate (ev->target_frame, false, true, false);
1013 _send_timecode_update = true;
1016 case SessionEvent::LocateRoll:
1017 if (ev->yes_or_no) {
1018 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1019 locate (ev->target_frame, true, true, false);
1021 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1022 start_locate (ev->target_frame, true, true, false);
1024 _send_timecode_update = true;
1027 case SessionEvent::LocateRollLocate:
1028 // locate is handled by ::request_roll_at_and_return()
1029 _requested_return_frame = ev->target_frame;
1030 request_locate (ev->target2_frame, true);
1034 case SessionEvent::SetTransportSpeed:
1035 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1038 case SessionEvent::PunchIn:
1039 // cerr << "PunchIN at " << transport_frame() << endl;
1040 if (config.get_punch_in() && record_status() == Enabled) {
1047 case SessionEvent::PunchOut:
1048 // cerr << "PunchOUT at " << transport_frame() << endl;
1049 if (config.get_punch_out()) {
1050 step_back_from_record ();
1056 case SessionEvent::StopOnce:
1057 if (!non_realtime_work_pending()) {
1058 stop_transport (ev->yes_or_no);
1059 _clear_event_type (SessionEvent::StopOnce);
1065 case SessionEvent::RangeStop:
1066 if (!non_realtime_work_pending()) {
1067 stop_transport (ev->yes_or_no);
1073 case SessionEvent::RangeLocate:
1074 start_locate (ev->target_frame, true, true, false);
1079 case SessionEvent::Overwrite:
1080 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1083 case SessionEvent::SetTrackSpeed:
1084 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1087 case SessionEvent::SetSyncSource:
1088 use_sync_source (ev->slave);
1091 case SessionEvent::Audition:
1092 set_audition (ev->region);
1093 // drop reference to region
1094 ev->region.reset ();
1097 case SessionEvent::InputConfigurationChange:
1098 add_post_transport_work (PostTransportInputChange);
1099 _butler->schedule_transport_work ();
1102 case SessionEvent::SetPlayAudioRange:
1103 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1106 case SessionEvent::RealTimeOperation:
1108 del = false; // other side of RT request needs to clean up
1111 case SessionEvent::AdjustPlaybackBuffering:
1112 schedule_playback_buffering_adjustment ();
1115 case SessionEvent::AdjustCaptureBuffering:
1116 schedule_capture_buffering_adjustment ();
1119 case SessionEvent::SetTimecodeTransmission:
1120 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1124 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1130 del = del && !_remove_event (ev);
1139 Session::compute_stop_limit () const
1141 bool const punching = (config.get_punch_in () && _locations->auto_punch_location());
1143 if (!actively_recording() && !punching && Config->get_stop_at_session_end()) {
1144 return current_end_frame ();
1147 return max_framepos;