possible fix for race between diskstream buffer overwrite and channel setup
[ardour2.git] / libs / ardour / session_process.cc
blob834280de917c34bfea38918bb76cfff4ea30a8c6
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/audio_diskstream.h"
32 #include "ardour/audioengine.h"
33 #include "ardour/auditioner.h"
34 #include "ardour/butler.h"
35 #include "ardour/debug.h"
36 #include "ardour/session.h"
37 #include "ardour/slave.h"
38 #include "ardour/timestamps.h"
40 #include "midi++/manager.h"
42 #include "i18n.h"
44 using namespace ARDOUR;
45 using namespace PBD;
46 using namespace std;
48 /** Called by the audio engine when there is work to be done with JACK.
49 * @param nframes Number of frames to process.
51 void
52 Session::process (nframes_t nframes)
54 MIDI::Manager::instance()->cycle_start(nframes);
56 _silent = false;
58 if (processing_blocked()) {
59 _silent = true;
60 return;
63 if (non_realtime_work_pending()) {
64 if (!_butler->transport_work_requested ()) {
65 post_transport ();
69 (this->*process_function) (nframes);
71 // the ticker is for sending time information like MidiClock
72 nframes_t transport_frames = transport_frame();
73 BBT_Time transport_bbt;
74 bbt_time(transport_frames, transport_bbt);
75 Timecode::Time transport_timecode;
76 timecode_time(transport_frames, transport_timecode);
77 tick (transport_frames, transport_bbt, transport_timecode); /* EMIT SIGNAL */
79 SendFeedback (); /* EMIT SIGNAL */
81 MIDI::Manager::instance()->cycle_end();
84 int
85 Session::fail_roll (nframes_t nframes)
87 return no_roll (nframes);
90 int
91 Session::no_roll (nframes_t nframes)
93 nframes_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
94 int ret = 0;
95 bool declick = get_transport_declick_required();
96 boost::shared_ptr<RouteList> r = routes.reader ();
98 if (_click_io) {
99 _click_io->silence (nframes);
102 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
104 if ((*i)->is_hidden()) {
105 continue;
108 (*i)->set_pending_declick (declick);
110 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending(),
111 actively_recording(), declick)) {
112 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
113 ret = -1;
114 break;
118 return ret;
122 Session::process_routes (nframes_t nframes, bool& need_butler)
124 bool record_active;
125 int declick = get_transport_declick_required();
126 bool rec_monitors = get_rec_monitors_input();
127 boost::shared_ptr<RouteList> r = routes.reader ();
129 if (transport_sub_state & StopPendingCapture) {
130 /* force a declick out */
131 declick = -1;
134 record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
136 const nframes_t start_frame = _transport_frame;
137 const nframes_t end_frame = _transport_frame + (nframes_t)floor(nframes * _transport_speed);
139 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
141 int ret;
143 if ((*i)->is_hidden()) {
144 continue;
147 (*i)->set_pending_declick (declick);
149 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, rec_monitors, need_butler)) < 0) {
150 stop_transport ();
151 return -1;
155 return 0;
159 Session::silent_process_routes (nframes_t nframes, bool& need_butler)
161 bool record_active = actively_recording();
162 int declick = get_transport_declick_required();
163 bool rec_monitors = get_rec_monitors_input();
164 boost::shared_ptr<RouteList> r = routes.reader ();
166 if (transport_sub_state & StopPendingCapture) {
167 /* force a declick out */
168 declick = -1;
171 const nframes_t start_frame = _transport_frame;
172 const nframes_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
174 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
176 int ret;
178 if ((*i)->is_hidden()) {
179 continue;
182 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, rec_monitors, need_butler)) < 0) {
183 stop_transport ();
184 return -1;
188 return 0;
191 void
192 Session::get_diskstream_statistics ()
194 float pworst = 1.0f;
195 float cworst = 1.0f;
197 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
198 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
200 if ((*i)->hidden()) {
201 continue;
204 pworst = min (pworst, (*i)->playback_buffer_load());
205 cworst = min (cworst, (*i)->capture_buffer_load());
208 uint32_t pmin = g_atomic_int_get (&_playback_load);
209 uint32_t pminold = g_atomic_int_get (&_playback_load_min);
210 uint32_t cmin = g_atomic_int_get (&_capture_load);
211 uint32_t cminold = g_atomic_int_get (&_capture_load_min);
213 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
214 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
215 g_atomic_int_set (&_playback_load_min, min (pmin, pminold));
216 g_atomic_int_set (&_capture_load_min, min (cmin, cminold));
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 nframes -= this_nframes;
357 if (frames_moved < 0) {
358 decrement_transport_position (-frames_moved);
359 } else {
360 increment_transport_position (frames_moved);
363 maybe_stop (stop_limit);
364 check_declick_out ();
367 _engine.split_cycle (this_nframes);
369 /* now handle this event and all others scheduled for the same time */
371 while (this_event && this_event->action_frame == _transport_frame) {
372 process_event (this_event);
374 if (the_next_one == events.end()) {
375 this_event = 0;
376 } else {
377 this_event = *the_next_one;
378 ++the_next_one;
382 /* if an event left our state changing, do the right thing */
384 if (nframes && non_realtime_work_pending()) {
385 no_roll (nframes);
386 break;
389 /* this is necessary to handle the case of seamless looping */
390 end_frame = _transport_frame + (nframes_t) floor (nframes * _transport_speed);
394 set_next_event ();
396 } /* implicit release of route lock */
398 if (session_needs_butler) {
399 _butler->summon ();
403 void
404 Session::reset_slave_state ()
406 average_slave_delta = 1800;
407 delta_accumulator_cnt = 0;
408 have_first_delta_accumulator = false;
409 _slave_state = Stopped;
412 bool
413 Session::transport_locked () const
415 Slave* sl = _slave;
417 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
418 return true;
421 return false;
424 bool
425 Session::follow_slave (nframes_t nframes)
427 double slave_speed;
428 nframes64_t slave_transport_frame;
429 nframes_t this_delta;
430 int dir;
432 if (!_slave->ok()) {
433 stop_transport ();
434 config.set_external_sync (false);
435 goto noroll;
438 _slave->speed_and_position (slave_speed, slave_transport_frame);
440 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
442 if (!_slave->locked()) {
443 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
444 goto noroll;
447 if (slave_transport_frame > _transport_frame) {
448 this_delta = slave_transport_frame - _transport_frame;
449 dir = 1;
450 } else {
451 this_delta = _transport_frame - slave_transport_frame;
452 dir = -1;
455 if (_slave->starting()) {
456 slave_speed = 0.0f;
459 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
461 /* if the TC source is synced, then we assume that its
462 speed is binary: 0.0 or 1.0
465 if (slave_speed != 0.0f) {
466 slave_speed = 1.0f;
469 } else {
471 /* if we are chasing and the average delta between us and the
472 master gets too big, we want to switch to silent
473 motion. so keep track of that here.
476 if (_slave_state == Running) {
477 calculate_moving_average_of_slave_delta(dir, this_delta);
481 track_slave_state (slave_speed, slave_transport_frame, this_delta);
483 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
484 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
487 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
489 if (_transport_speed != 0.0f) {
492 note that average_dir is +1 or -1
495 float delta;
497 if (average_slave_delta == 0) {
498 delta = this_delta;
499 delta *= dir;
500 } else {
501 delta = average_slave_delta;
502 delta *= average_dir;
505 #ifndef NDEBUG
506 if (slave_speed != 0.0) {
507 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
508 (int) (dir * this_delta),
509 slave_speed,
510 _transport_speed,
511 _transport_frame,
512 slave_transport_frame,
513 average_slave_delta));
515 #endif
517 if (_slave->give_slave_full_control_over_transport_speed()) {
518 set_transport_speed (slave_speed, false, false);
519 //std::cout << "set speed = " << slave_speed << "\n";
520 } else {
521 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
522 request_transport_speed (adjusted_speed);
523 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
524 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
525 slave_speed));
528 #if 1
529 if ((nframes_t) abs(average_slave_delta) > _slave->resolution()) {
530 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
531 goto silent_motion;
533 #endif
538 if (_slave_state == Running && !non_realtime_work_pending()) {
539 /* speed is set, we're locked, and good to go */
540 return true;
543 silent_motion:
544 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
545 follow_slave_silently (nframes, slave_speed);
547 noroll:
548 /* don't move at all */
549 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
550 no_roll (nframes);
551 return false;
554 void
555 Session::calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta)
557 if (delta_accumulator_cnt >= delta_accumulator_size) {
558 have_first_delta_accumulator = true;
559 delta_accumulator_cnt = 0;
562 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
563 delta_accumulator[delta_accumulator_cnt++] = long(dir) * long(this_delta);
566 if (have_first_delta_accumulator) {
567 average_slave_delta = 0L;
568 for (int i = 0; i < delta_accumulator_size; ++i) {
569 average_slave_delta += delta_accumulator[i];
571 average_slave_delta /= long(delta_accumulator_size);
572 if (average_slave_delta < 0L) {
573 average_dir = -1;
574 average_slave_delta = abs(average_slave_delta);
575 } else {
576 average_dir = 1;
581 void
582 Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta)
584 if (slave_speed != 0.0f) {
586 /* slave is running */
588 switch (_slave_state) {
589 case Stopped:
590 if (_slave->requires_seekahead()) {
591 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
592 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
593 /* we can call locate() here because we are in process context */
594 locate (slave_wait_end, false, false);
595 _slave_state = Waiting;
597 } else {
599 _slave_state = Running;
601 Location* al = _locations.auto_loop_location();
603 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
604 // cancel looping
605 request_play_loop(false);
608 if (slave_transport_frame != _transport_frame) {
609 locate (slave_transport_frame, false, false);
612 break;
614 case Waiting:
615 default:
616 break;
619 if (_slave_state == Waiting) {
621 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
623 if (slave_transport_frame >= slave_wait_end) {
625 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
627 _slave_state = Running;
629 /* now perform a "micro-seek" within the disk buffers to realign ourselves
630 precisely with the master.
634 bool ok = true;
635 nframes_t frame_delta = slave_transport_frame - _transport_frame;
637 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
639 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
640 if (!(*i)->can_internal_playback_seek (frame_delta)) {
641 ok = false;
642 break;
646 if (ok) {
647 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
648 (*i)->internal_playback_seek (frame_delta);
650 _transport_frame += frame_delta;
652 } else {
653 cerr << "cannot micro-seek\n";
654 /* XXX what? */
657 memset (delta_accumulator, 0, sizeof (long) * delta_accumulator_size);
658 average_slave_delta = 0L;
659 this_delta = 0;
663 if (_slave_state == Running && _transport_speed == 0.0f) {
664 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
665 start_transport ();
668 } else { // slave_speed is 0
670 /* slave has stopped */
672 if (_transport_speed != 0.0f) {
673 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
674 stop_transport();
677 if (slave_transport_frame != _transport_frame) {
678 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
679 force_locate (slave_transport_frame, false);
682 _slave_state = Stopped;
686 void
687 Session::follow_slave_silently (nframes_t nframes, float slave_speed)
689 if (slave_speed && _transport_speed) {
691 /* something isn't right, but we should move with the master
692 for now.
695 bool need_butler;
697 silent_process_routes (nframes, need_butler);
699 if (need_butler) {
700 _butler->summon ();
703 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
705 if (frames_moved < 0) {
706 decrement_transport_position (-frames_moved);
707 } else {
708 increment_transport_position (frames_moved);
711 nframes_t stop_limit;
713 if (actively_recording()) {
714 stop_limit = max_frames;
715 } else {
716 if (Config->get_stop_at_session_end()) {
717 stop_limit = current_end_frame();
718 } else {
719 stop_limit = max_frames;
723 maybe_stop (stop_limit);
727 void
728 Session::process_without_events (nframes_t nframes)
730 bool session_needs_butler = false;
731 nframes_t stop_limit;
732 long frames_moved;
734 if (!process_can_proceed()) {
735 _silent = true;
736 return;
739 if (!_exporting && _slave) {
740 if (!follow_slave (nframes)) {
741 return;
745 if (_transport_speed == 0) {
746 fail_roll (nframes);
747 return;
750 if (!_exporting) {
751 send_midi_time_code_for_cycle (nframes);
754 if (actively_recording()) {
755 stop_limit = max_frames;
756 } else {
757 if (Config->get_stop_at_session_end()) {
758 stop_limit = current_end_frame();
759 } else {
760 stop_limit = max_frames;
764 if (maybe_stop (stop_limit)) {
765 fail_roll (nframes);
766 return;
769 if (maybe_sync_start (nframes)) {
770 return;
773 click (_transport_frame, nframes);
775 if (_transport_speed == 1.0) {
776 frames_moved = (long) nframes;
777 } else {
778 interpolation.set_target_speed (fabs(_target_transport_speed));
779 interpolation.set_speed (fabs(_transport_speed));
780 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
783 if (process_routes (nframes, session_needs_butler)) {
784 fail_roll (nframes);
785 return;
788 if (frames_moved < 0) {
789 decrement_transport_position (-frames_moved);
790 } else {
791 increment_transport_position (frames_moved);
794 maybe_stop (stop_limit);
795 check_declick_out ();
797 if (session_needs_butler) {
798 _butler->summon ();
802 /** Process callback used when the auditioner is active.
803 * @param nframes number of frames to process.
805 void
806 Session::process_audition (nframes_t nframes)
808 SessionEvent* ev;
809 boost::shared_ptr<RouteList> r = routes.reader ();
811 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
812 if (!(*i)->is_hidden()) {
813 (*i)->silence (nframes);
817 /* run the auditioner, and if it says we need butler service, ask for it */
819 if (auditioner->play_audition (nframes) > 0) {
820 _butler->summon ();
823 /* if using a monitor section, run it because otherwise we don't hear anything */
825 if (auditioner->needs_monitor()) {
826 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
829 /* handle pending events */
831 while (pending_events.read (&ev, 1) == 1) {
832 merge_event (ev);
835 /* if we are not in the middle of a state change,
836 and there are immediate events queued up,
837 process them.
840 while (!non_realtime_work_pending() && !immediate_events.empty()) {
841 SessionEvent *ev = immediate_events.front ();
842 immediate_events.pop_front ();
843 process_event (ev);
846 if (!auditioner->auditioning()) {
847 /* auditioner no longer active, so go back to the normal process callback */
848 process_function = &Session::process_with_events;
852 bool
853 Session::maybe_sync_start (nframes_t& nframes)
855 nframes_t sync_offset;
857 if (!waiting_for_sync_offset) {
858 return false;
861 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
863 /* generate silence up to the sync point, then
864 adjust nframes + offset to reflect whatever
865 is left to do.
868 no_roll (sync_offset);
869 nframes -= sync_offset;
870 Port::increment_port_offset (sync_offset);
871 waiting_for_sync_offset = false;
873 if (nframes == 0) {
874 return true; // done, nothing left to process
877 } else {
879 /* sync offset point is not within this process()
880 cycle, so just generate silence. and don't bother
881 with any fancy stuff here, just the minimal silence.
884 _silent = true;
886 if (Config->get_locate_while_waiting_for_sync()) {
887 if (micro_locate (nframes)) {
888 /* XXX ERROR !!! XXX */
892 return true; // done, nothing left to process
895 return false;
898 void
899 Session::queue_event (SessionEvent* ev)
901 if (_state_of_the_state & Deletion) {
902 return;
903 } else if (_state_of_the_state & Loading) {
904 merge_event (ev);
905 } else {
906 pending_events.write (&ev, 1);
910 void
911 Session::set_next_event ()
913 if (events.empty()) {
914 next_event = events.end();
915 return;
918 if (next_event == events.end()) {
919 next_event = events.begin();
922 if ((*next_event)->action_frame > _transport_frame) {
923 next_event = events.begin();
926 for (; next_event != events.end(); ++next_event) {
927 if ((*next_event)->action_frame >= _transport_frame) {
928 break;
933 void
934 Session::process_event (SessionEvent* ev)
936 bool remove = true;
937 bool del = true;
939 /* if we're in the middle of a state change (i.e. waiting
940 for the butler thread to complete the non-realtime
941 part of the change), we'll just have to queue this
942 event for a time when the change is complete.
945 if (non_realtime_work_pending()) {
947 /* except locates, which we have the capability to handle */
949 if (ev->type != SessionEvent::Locate) {
950 immediate_events.insert (immediate_events.end(), ev);
951 _remove_event (ev);
952 return;
956 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
958 switch (ev->type) {
959 case SessionEvent::SetLoop:
960 set_play_loop (ev->yes_or_no);
961 break;
963 case SessionEvent::AutoLoop:
964 if (play_loop) {
965 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
967 remove = false;
968 del = false;
969 break;
971 case SessionEvent::Locate:
972 if (ev->yes_or_no) {
973 // cerr << "forced locate to " << ev->target_frame << endl;
974 locate (ev->target_frame, false, true, false);
975 } else {
976 // cerr << "soft locate to " << ev->target_frame << endl;
977 start_locate (ev->target_frame, false, true, false);
979 _send_timecode_update = true;
980 break;
982 case SessionEvent::LocateRoll:
983 if (ev->yes_or_no) {
984 // cerr << "forced locate to+roll " << ev->target_frame << endl;
985 locate (ev->target_frame, true, true, false);
986 } else {
987 // cerr << "soft locate to+roll " << ev->target_frame << endl;
988 start_locate (ev->target_frame, true, true, false);
990 _send_timecode_update = true;
991 break;
993 case SessionEvent::LocateRollLocate:
994 // locate is handled by ::request_roll_at_and_return()
995 _requested_return_frame = ev->target_frame;
996 request_locate (ev->target2_frame, true);
997 break;
1000 case SessionEvent::SetTransportSpeed:
1001 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1002 break;
1004 case SessionEvent::PunchIn:
1005 // cerr << "PunchIN at " << transport_frame() << endl;
1006 if (config.get_punch_in() && record_status() == Enabled) {
1007 enable_record ();
1009 remove = false;
1010 del = false;
1011 break;
1013 case SessionEvent::PunchOut:
1014 // cerr << "PunchOUT at " << transport_frame() << endl;
1015 if (config.get_punch_out()) {
1016 step_back_from_record ();
1018 remove = false;
1019 del = false;
1020 break;
1022 case SessionEvent::StopOnce:
1023 if (!non_realtime_work_pending()) {
1024 stop_transport (ev->yes_or_no);
1025 _clear_event_type (SessionEvent::StopOnce);
1027 remove = false;
1028 del = false;
1029 break;
1031 case SessionEvent::RangeStop:
1032 if (!non_realtime_work_pending()) {
1033 stop_transport (ev->yes_or_no);
1035 remove = false;
1036 del = false;
1037 break;
1039 case SessionEvent::RangeLocate:
1040 start_locate (ev->target_frame, true, true, false);
1041 remove = false;
1042 del = false;
1043 break;
1045 case SessionEvent::Overwrite:
1046 overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
1047 break;
1049 case SessionEvent::SetDiskstreamSpeed:
1050 set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
1051 break;
1053 case SessionEvent::SetSyncSource:
1054 use_sync_source (ev->slave);
1055 break;
1057 case SessionEvent::Audition:
1058 set_audition (ev->region);
1059 // drop reference to region
1060 ev->region.reset ();
1061 break;
1063 case SessionEvent::InputConfigurationChange:
1064 add_post_transport_work (PostTransportInputChange);
1065 _butler->schedule_transport_work ();
1066 break;
1068 case SessionEvent::SetPlayAudioRange:
1069 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1070 break;
1072 case SessionEvent::RealTimeOperation:
1073 process_rtop (ev);
1074 del = false; // other side of RT request needs to clean up
1075 break;
1077 default:
1078 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1079 /*NOTREACHED*/
1080 break;
1083 if (remove) {
1084 del = del && !_remove_event (ev);
1087 if (del) {
1088 delete ev;