Reset buffer stats on stop. Remove unused minimum playback/capture load stats.
[ardour2.git] / libs / ardour / session_process.cc
blob94527c6646192184814b6f9c636a2f057bef3c96
1 /*
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.
20 #include <cmath>
21 #include <cerrno>
22 #include <algorithm>
23 #include <unistd.h>
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/port.h"
41 #include "midi++/manager.h"
43 #include "i18n.h"
45 using namespace ARDOUR;
46 using namespace PBD;
47 using namespace std;
49 /** Called by the audio engine when there is work to be done with JACK.
50 * @param nframes Number of frames to process.
52 void
53 Session::process (nframes_t nframes)
55 MIDI::Manager::instance()->cycle_start(nframes);
57 _silent = false;
59 if (processing_blocked()) {
60 _silent = true;
61 return;
64 if (non_realtime_work_pending()) {
65 if (!_butler->transport_work_requested ()) {
66 post_transport ();
70 _engine.main_thread()->get_buffers ();
72 (this->*process_function) (nframes);
74 _engine.main_thread()->drop_buffers ();
76 // the ticker is for sending time information like MidiClock
77 nframes_t transport_frames = transport_frame();
78 BBT_Time transport_bbt;
79 bbt_time(transport_frames, transport_bbt);
80 Timecode::Time transport_timecode;
81 timecode_time(transport_frames, transport_timecode);
82 tick (transport_frames, transport_bbt, transport_timecode); /* EMIT SIGNAL */
84 SendFeedback (); /* EMIT SIGNAL */
86 MIDI::Manager::instance()->cycle_end();
89 int
90 Session::fail_roll (nframes_t nframes)
92 return no_roll (nframes);
95 int
96 Session::no_roll (nframes_t nframes)
98 nframes_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
99 int ret = 0;
100 bool declick = get_transport_declick_required();
101 boost::shared_ptr<RouteList> r = routes.reader ();
103 if (_click_io) {
104 _click_io->silence (nframes);
107 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
109 if ((*i)->is_hidden()) {
110 continue;
113 (*i)->set_pending_declick (declick);
115 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending(),
116 actively_recording(), declick)) {
117 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
118 ret = -1;
119 break;
123 return ret;
127 Session::process_routes (nframes_t nframes, bool& need_butler)
129 bool record_active;
130 int declick = get_transport_declick_required();
131 bool rec_monitors = get_rec_monitors_input();
132 boost::shared_ptr<RouteList> r = routes.reader ();
134 if (transport_sub_state & StopPendingCapture) {
135 /* force a declick out */
136 declick = -1;
139 record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
141 const nframes_t start_frame = _transport_frame;
142 const nframes_t end_frame = _transport_frame + (nframes_t)floor(nframes * _transport_speed);
144 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
146 int ret;
148 if ((*i)->is_hidden()) {
149 continue;
152 (*i)->set_pending_declick (declick);
154 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, rec_monitors, need_butler)) < 0) {
155 stop_transport ();
156 return -1;
160 return 0;
164 Session::silent_process_routes (nframes_t nframes, bool& need_butler)
166 bool record_active = actively_recording();
167 int declick = get_transport_declick_required();
168 bool rec_monitors = get_rec_monitors_input();
169 boost::shared_ptr<RouteList> r = routes.reader ();
171 if (transport_sub_state & StopPendingCapture) {
172 /* force a declick out */
173 declick = -1;
176 const nframes_t start_frame = _transport_frame;
177 const nframes_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
179 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
181 int ret;
183 if ((*i)->is_hidden()) {
184 continue;
187 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, rec_monitors, need_butler)) < 0) {
188 stop_transport ();
189 return -1;
193 return 0;
196 void
197 Session::get_track_statistics ()
199 float pworst = 1.0f;
200 float cworst = 1.0f;
202 boost::shared_ptr<RouteList> rl = routes.reader();
203 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
205 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
207 if (!tr || tr->hidden()) {
208 continue;
211 pworst = min (pworst, tr->playback_buffer_load());
212 cworst = min (cworst, tr->capture_buffer_load());
215 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
216 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
218 if (actively_recording()) {
219 set_dirty();
223 /** Process callback used when the auditioner is not active */
224 void
225 Session::process_with_events (nframes_t nframes)
227 SessionEvent* ev;
228 nframes_t this_nframes;
229 nframes_t end_frame;
230 bool session_needs_butler = false;
231 nframes_t stop_limit;
232 long frames_moved;
234 /* make sure the auditioner is silent */
236 if (auditioner) {
237 auditioner->silence (nframes);
240 /* handle any pending events */
242 while (pending_events.read (&ev, 1) == 1) {
243 merge_event (ev);
246 /* if we are not in the middle of a state change,
247 and there are immediate events queued up,
248 process them.
251 while (!non_realtime_work_pending() && !immediate_events.empty()) {
252 SessionEvent *ev = immediate_events.front ();
253 immediate_events.pop_front ();
254 process_event (ev);
257 /* Events caused a transport change, send an MTC Full Frame (Timecode) message.
258 * This is sent whether rolling or not, to give slaves an idea of ardour time
259 * on locates (and allow slow slaves to position and prepare for rolling)
261 if (_send_timecode_update) {
262 send_full_time_code(nframes);
263 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
266 if (!process_can_proceed()) {
267 _silent = true;
268 return;
271 if (events.empty() || next_event == events.end()) {
272 process_without_events (nframes);
273 return;
276 if (_transport_speed == 1.0) {
277 frames_moved = (long) nframes;
278 } else {
279 interpolation.set_target_speed (fabs(_target_transport_speed));
280 interpolation.set_speed (fabs(_transport_speed));
281 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
284 end_frame = _transport_frame + (nframes_t)frames_moved;
287 SessionEvent* this_event;
288 Events::iterator the_next_one;
290 if (!process_can_proceed()) {
291 _silent = true;
292 return;
295 if (!_exporting && _slave) {
296 if (!follow_slave (nframes)) {
297 return;
301 if (_transport_speed == 0) {
302 no_roll (nframes);
303 return;
306 if (!_exporting) {
307 send_midi_time_code_for_cycle (nframes);
310 if (actively_recording()) {
311 stop_limit = max_frames;
312 } else {
314 if (Config->get_stop_at_session_end()) {
315 stop_limit = current_end_frame();
316 } else {
317 stop_limit = max_frames;
321 if (maybe_stop (stop_limit)) {
322 no_roll (nframes);
323 return;
326 this_event = *next_event;
327 the_next_one = next_event;
328 ++the_next_one;
330 /* yes folks, here it is, the actual loop where we really truly
331 process some audio
334 while (nframes) {
336 this_nframes = nframes; /* real (jack) time relative */
337 frames_moved = (long) floor (_transport_speed * nframes); /* transport relative */
339 /* running an event, position transport precisely to its time */
340 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
341 /* this isn't quite right for reverse play */
342 frames_moved = (long) (this_event->action_frame - _transport_frame);
343 this_nframes = (nframes_t) abs( floor(frames_moved / _transport_speed) );
346 if (this_nframes) {
348 click (_transport_frame, this_nframes);
350 if (process_routes (this_nframes, session_needs_butler)) {
351 fail_roll (nframes);
352 return;
355 get_track_statistics ();
357 nframes -= this_nframes;
359 if (frames_moved < 0) {
360 decrement_transport_position (-frames_moved);
361 } else {
362 increment_transport_position (frames_moved);
365 maybe_stop (stop_limit);
366 check_declick_out ();
369 _engine.split_cycle (this_nframes);
371 /* now handle this event and all others scheduled for the same time */
373 while (this_event && this_event->action_frame == _transport_frame) {
374 process_event (this_event);
376 if (the_next_one == events.end()) {
377 this_event = 0;
378 } else {
379 this_event = *the_next_one;
380 ++the_next_one;
384 /* if an event left our state changing, do the right thing */
386 if (nframes && non_realtime_work_pending()) {
387 no_roll (nframes);
388 break;
391 /* this is necessary to handle the case of seamless looping */
392 end_frame = _transport_frame + (nframes_t) floor (nframes * _transport_speed);
396 set_next_event ();
398 } /* implicit release of route lock */
400 if (session_needs_butler) {
401 _butler->summon ();
405 void
406 Session::reset_slave_state ()
408 average_slave_delta = 1800;
409 delta_accumulator_cnt = 0;
410 have_first_delta_accumulator = false;
411 _slave_state = Stopped;
414 bool
415 Session::transport_locked () const
417 Slave* sl = _slave;
419 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
420 return true;
423 return false;
426 bool
427 Session::follow_slave (nframes_t nframes)
429 double slave_speed;
430 nframes64_t slave_transport_frame;
431 nframes_t this_delta;
432 int dir;
434 if (!_slave->ok()) {
435 stop_transport ();
436 config.set_external_sync (false);
437 goto noroll;
440 _slave->speed_and_position (slave_speed, slave_transport_frame);
442 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
444 if (!_slave->locked()) {
445 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
446 goto noroll;
449 if (slave_transport_frame > _transport_frame) {
450 this_delta = slave_transport_frame - _transport_frame;
451 dir = 1;
452 } else {
453 this_delta = _transport_frame - slave_transport_frame;
454 dir = -1;
457 if (_slave->starting()) {
458 slave_speed = 0.0f;
461 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
463 /* if the TC source is synced, then we assume that its
464 speed is binary: 0.0 or 1.0
467 if (slave_speed != 0.0f) {
468 slave_speed = 1.0f;
471 } else {
473 /* if we are chasing and the average delta between us and the
474 master gets too big, we want to switch to silent
475 motion. so keep track of that here.
478 if (_slave_state == Running) {
479 calculate_moving_average_of_slave_delta(dir, this_delta);
483 track_slave_state (slave_speed, slave_transport_frame, this_delta);
485 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
486 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
489 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
491 if (_transport_speed != 0.0f) {
494 note that average_dir is +1 or -1
497 float delta;
499 if (average_slave_delta == 0) {
500 delta = this_delta;
501 delta *= dir;
502 } else {
503 delta = average_slave_delta;
504 delta *= average_dir;
507 #ifndef NDEBUG
508 if (slave_speed != 0.0) {
509 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
510 (int) (dir * this_delta),
511 slave_speed,
512 _transport_speed,
513 _transport_frame,
514 slave_transport_frame,
515 average_slave_delta));
517 #endif
519 if (_slave->give_slave_full_control_over_transport_speed()) {
520 set_transport_speed (slave_speed, false, false);
521 //std::cout << "set speed = " << slave_speed << "\n";
522 } else {
523 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
524 request_transport_speed (adjusted_speed);
525 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
526 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
527 slave_speed));
530 #if 1
531 if ((nframes_t) abs(average_slave_delta) > _slave->resolution()) {
532 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
533 goto silent_motion;
535 #endif
540 if (_slave_state == Running && !non_realtime_work_pending()) {
541 /* speed is set, we're locked, and good to go */
542 return true;
545 silent_motion:
546 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
547 follow_slave_silently (nframes, slave_speed);
549 noroll:
550 /* don't move at all */
551 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
552 no_roll (nframes);
553 return false;
556 void
557 Session::calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta)
559 if (delta_accumulator_cnt >= delta_accumulator_size) {
560 have_first_delta_accumulator = true;
561 delta_accumulator_cnt = 0;
564 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
565 delta_accumulator[delta_accumulator_cnt++] = long(dir) * long(this_delta);
568 if (have_first_delta_accumulator) {
569 average_slave_delta = 0L;
570 for (int i = 0; i < delta_accumulator_size; ++i) {
571 average_slave_delta += delta_accumulator[i];
573 average_slave_delta /= long(delta_accumulator_size);
574 if (average_slave_delta < 0L) {
575 average_dir = -1;
576 average_slave_delta = abs(average_slave_delta);
577 } else {
578 average_dir = 1;
583 void
584 Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta)
586 if (slave_speed != 0.0f) {
588 /* slave is running */
590 switch (_slave_state) {
591 case Stopped:
592 if (_slave->requires_seekahead()) {
593 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
594 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
595 /* we can call locate() here because we are in process context */
596 locate (slave_wait_end, false, false);
597 _slave_state = Waiting;
599 } else {
601 _slave_state = Running;
603 Location* al = _locations.auto_loop_location();
605 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
606 // cancel looping
607 request_play_loop(false);
610 if (slave_transport_frame != _transport_frame) {
611 locate (slave_transport_frame, false, false);
614 break;
616 case Waiting:
617 default:
618 break;
621 if (_slave_state == Waiting) {
623 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
625 if (slave_transport_frame >= slave_wait_end) {
627 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
629 _slave_state = Running;
631 /* now perform a "micro-seek" within the disk buffers to realign ourselves
632 precisely with the master.
636 bool ok = true;
637 nframes_t frame_delta = slave_transport_frame - _transport_frame;
639 boost::shared_ptr<RouteList> rl = routes.reader();
640 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
641 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
642 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
643 ok = false;
644 break;
648 if (ok) {
649 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
650 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
651 if (tr) {
652 tr->internal_playback_seek (frame_delta);
655 _transport_frame += frame_delta;
657 } else {
658 cerr << "cannot micro-seek\n";
659 /* XXX what? */
662 memset (delta_accumulator, 0, sizeof (long) * delta_accumulator_size);
663 average_slave_delta = 0L;
664 this_delta = 0;
668 if (_slave_state == Running && _transport_speed == 0.0f) {
669 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
670 start_transport ();
673 } else { // slave_speed is 0
675 /* slave has stopped */
677 if (_transport_speed != 0.0f) {
678 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
679 stop_transport();
682 if (slave_transport_frame != _transport_frame) {
683 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
684 force_locate (slave_transport_frame, false);
687 _slave_state = Stopped;
691 void
692 Session::follow_slave_silently (nframes_t nframes, float slave_speed)
694 if (slave_speed && _transport_speed) {
696 /* something isn't right, but we should move with the master
697 for now.
700 bool need_butler;
702 silent_process_routes (nframes, need_butler);
704 get_track_statistics ();
706 if (need_butler) {
707 _butler->summon ();
710 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
712 if (frames_moved < 0) {
713 decrement_transport_position (-frames_moved);
714 } else {
715 increment_transport_position (frames_moved);
718 nframes_t stop_limit;
720 if (actively_recording()) {
721 stop_limit = max_frames;
722 } else {
723 if (Config->get_stop_at_session_end()) {
724 stop_limit = current_end_frame();
725 } else {
726 stop_limit = max_frames;
730 maybe_stop (stop_limit);
734 void
735 Session::process_without_events (nframes_t nframes)
737 bool session_needs_butler = false;
738 nframes_t stop_limit;
739 long frames_moved;
741 if (!process_can_proceed()) {
742 _silent = true;
743 return;
746 if (!_exporting && _slave) {
747 if (!follow_slave (nframes)) {
748 return;
752 if (_transport_speed == 0) {
753 fail_roll (nframes);
754 return;
757 if (!_exporting) {
758 send_midi_time_code_for_cycle (nframes);
761 if (actively_recording()) {
762 stop_limit = max_frames;
763 } else {
764 if (Config->get_stop_at_session_end()) {
765 stop_limit = current_end_frame();
766 } else {
767 stop_limit = max_frames;
771 if (maybe_stop (stop_limit)) {
772 fail_roll (nframes);
773 return;
776 if (maybe_sync_start (nframes)) {
777 return;
780 click (_transport_frame, nframes);
782 if (_transport_speed == 1.0) {
783 frames_moved = (long) nframes;
784 } else {
785 interpolation.set_target_speed (fabs(_target_transport_speed));
786 interpolation.set_speed (fabs(_transport_speed));
787 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
790 if (process_routes (nframes, session_needs_butler)) {
791 fail_roll (nframes);
792 return;
795 get_track_statistics ();
797 if (frames_moved < 0) {
798 decrement_transport_position (-frames_moved);
799 } else {
800 increment_transport_position (frames_moved);
803 maybe_stop (stop_limit);
804 check_declick_out ();
806 if (session_needs_butler) {
807 _butler->summon ();
811 /** Process callback used when the auditioner is active.
812 * @param nframes number of frames to process.
814 void
815 Session::process_audition (nframes_t nframes)
817 SessionEvent* ev;
818 boost::shared_ptr<RouteList> r = routes.reader ();
820 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
821 if (!(*i)->is_hidden()) {
822 (*i)->silence (nframes);
826 /* run the auditioner, and if it says we need butler service, ask for it */
828 if (auditioner->play_audition (nframes) > 0) {
829 _butler->summon ();
832 /* if using a monitor section, run it because otherwise we don't hear anything */
834 if (auditioner->needs_monitor()) {
835 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
838 /* handle pending events */
840 while (pending_events.read (&ev, 1) == 1) {
841 merge_event (ev);
844 /* if we are not in the middle of a state change,
845 and there are immediate events queued up,
846 process them.
849 while (!non_realtime_work_pending() && !immediate_events.empty()) {
850 SessionEvent *ev = immediate_events.front ();
851 immediate_events.pop_front ();
852 process_event (ev);
855 if (!auditioner->auditioning()) {
856 /* auditioner no longer active, so go back to the normal process callback */
857 process_function = &Session::process_with_events;
861 bool
862 Session::maybe_sync_start (nframes_t& nframes)
864 nframes_t sync_offset;
866 if (!waiting_for_sync_offset) {
867 return false;
870 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
872 /* generate silence up to the sync point, then
873 adjust nframes + offset to reflect whatever
874 is left to do.
877 no_roll (sync_offset);
878 nframes -= sync_offset;
879 Port::increment_port_offset (sync_offset);
880 waiting_for_sync_offset = false;
882 if (nframes == 0) {
883 return true; // done, nothing left to process
886 } else {
888 /* sync offset point is not within this process()
889 cycle, so just generate silence. and don't bother
890 with any fancy stuff here, just the minimal silence.
893 _silent = true;
895 if (Config->get_locate_while_waiting_for_sync()) {
896 if (micro_locate (nframes)) {
897 /* XXX ERROR !!! XXX */
901 return true; // done, nothing left to process
904 return false;
907 void
908 Session::queue_event (SessionEvent* ev)
910 if (_state_of_the_state & Deletion) {
911 return;
912 } else if (_state_of_the_state & Loading) {
913 merge_event (ev);
914 } else {
915 pending_events.write (&ev, 1);
919 void
920 Session::set_next_event ()
922 if (events.empty()) {
923 next_event = events.end();
924 return;
927 if (next_event == events.end()) {
928 next_event = events.begin();
931 if ((*next_event)->action_frame > _transport_frame) {
932 next_event = events.begin();
935 for (; next_event != events.end(); ++next_event) {
936 if ((*next_event)->action_frame >= _transport_frame) {
937 break;
942 void
943 Session::process_event (SessionEvent* ev)
945 bool remove = true;
946 bool del = true;
948 /* if we're in the middle of a state change (i.e. waiting
949 for the butler thread to complete the non-realtime
950 part of the change), we'll just have to queue this
951 event for a time when the change is complete.
954 if (non_realtime_work_pending()) {
956 /* except locates, which we have the capability to handle */
958 if (ev->type != SessionEvent::Locate) {
959 immediate_events.insert (immediate_events.end(), ev);
960 _remove_event (ev);
961 return;
965 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
967 switch (ev->type) {
968 case SessionEvent::SetLoop:
969 set_play_loop (ev->yes_or_no);
970 break;
972 case SessionEvent::AutoLoop:
973 if (play_loop) {
974 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
976 remove = false;
977 del = false;
978 break;
980 case SessionEvent::Locate:
981 if (ev->yes_or_no) {
982 // cerr << "forced locate to " << ev->target_frame << endl;
983 locate (ev->target_frame, false, true, false);
984 } else {
985 // cerr << "soft locate to " << ev->target_frame << endl;
986 start_locate (ev->target_frame, false, true, false);
988 _send_timecode_update = true;
989 break;
991 case SessionEvent::LocateRoll:
992 if (ev->yes_or_no) {
993 // cerr << "forced locate to+roll " << ev->target_frame << endl;
994 locate (ev->target_frame, true, true, false);
995 } else {
996 // cerr << "soft locate to+roll " << ev->target_frame << endl;
997 start_locate (ev->target_frame, true, true, false);
999 _send_timecode_update = true;
1000 break;
1002 case SessionEvent::LocateRollLocate:
1003 // locate is handled by ::request_roll_at_and_return()
1004 _requested_return_frame = ev->target_frame;
1005 request_locate (ev->target2_frame, true);
1006 break;
1009 case SessionEvent::SetTransportSpeed:
1010 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1011 break;
1013 case SessionEvent::PunchIn:
1014 // cerr << "PunchIN at " << transport_frame() << endl;
1015 if (config.get_punch_in() && record_status() == Enabled) {
1016 enable_record ();
1018 remove = false;
1019 del = false;
1020 break;
1022 case SessionEvent::PunchOut:
1023 // cerr << "PunchOUT at " << transport_frame() << endl;
1024 if (config.get_punch_out()) {
1025 step_back_from_record ();
1027 remove = false;
1028 del = false;
1029 break;
1031 case SessionEvent::StopOnce:
1032 if (!non_realtime_work_pending()) {
1033 stop_transport (ev->yes_or_no);
1034 _clear_event_type (SessionEvent::StopOnce);
1036 remove = false;
1037 del = false;
1038 break;
1040 case SessionEvent::RangeStop:
1041 if (!non_realtime_work_pending()) {
1042 stop_transport (ev->yes_or_no);
1044 remove = false;
1045 del = false;
1046 break;
1048 case SessionEvent::RangeLocate:
1049 start_locate (ev->target_frame, true, true, false);
1050 remove = false;
1051 del = false;
1052 break;
1054 case SessionEvent::Overwrite:
1055 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1056 break;
1058 case SessionEvent::SetTrackSpeed:
1059 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1060 break;
1062 case SessionEvent::SetSyncSource:
1063 use_sync_source (ev->slave);
1064 break;
1066 case SessionEvent::Audition:
1067 set_audition (ev->region);
1068 // drop reference to region
1069 ev->region.reset ();
1070 break;
1072 case SessionEvent::InputConfigurationChange:
1073 add_post_transport_work (PostTransportInputChange);
1074 _butler->schedule_transport_work ();
1075 break;
1077 case SessionEvent::SetPlayAudioRange:
1078 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1079 break;
1081 case SessionEvent::RealTimeOperation:
1082 process_rtop (ev);
1083 del = false; // other side of RT request needs to clean up
1084 break;
1086 default:
1087 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1088 /*NOTREACHED*/
1089 break;
1092 if (remove) {
1093 del = del && !_remove_event (ev);
1096 if (del) {
1097 delete ev;