fix assumption that Session::_mmc != 0
[ardour2.git] / libs / ardour / session_process.cc
blob5c67b6b2993a44d0c2cdc2d29330fc80a8687fa8
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/graph.h"
40 #include "ardour/port.h"
42 #include "midi++/manager.h"
43 #include "midi++/mmc.h"
45 #include "i18n.h"
47 using namespace ARDOUR;
48 using namespace PBD;
49 using namespace std;
51 /** Called by the audio engine when there is work to be done with JACK.
52 * @param nframes Number of frames to process.
54 void
55 Session::process (nframes_t nframes)
57 MIDI::Manager::instance()->cycle_start(nframes);
59 _silent = false;
61 if (processing_blocked()) {
62 _silent = true;
63 return;
66 if (non_realtime_work_pending()) {
67 if (!_butler->transport_work_requested ()) {
68 post_transport ();
72 if (_mmc) {
73 _mmc->flush_pending ();
76 _engine.main_thread()->get_buffers ();
78 (this->*process_function) (nframes);
80 _engine.main_thread()->drop_buffers ();
82 // the ticker is for sending time information like MidiClock
83 nframes_t transport_frames = transport_frame();
84 BBT_Time transport_bbt;
85 bbt_time(transport_frames, transport_bbt);
86 Timecode::Time transport_timecode;
87 timecode_time(transport_frames, transport_timecode);
88 tick (transport_frames, transport_bbt, transport_timecode); /* EMIT SIGNAL */
90 SendFeedback (); /* EMIT SIGNAL */
92 MIDI::Manager::instance()->cycle_end();
95 int
96 Session::fail_roll (nframes_t nframes)
98 return no_roll (nframes);
102 Session::no_roll (nframes_t nframes)
104 nframes_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
105 int ret = 0;
106 bool declick = get_transport_declick_required();
107 boost::shared_ptr<RouteList> r = routes.reader ();
109 if (_click_io) {
110 _click_io->silence (nframes);
113 route_graph->routes_no_roll( nframes, _transport_frame, end_frame, non_realtime_work_pending(), actively_recording(), declick);
115 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
117 if ((*i)->is_hidden()) {
118 continue;
121 (*i)->set_pending_declick (declick);
123 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending(),
124 actively_recording(), declick)) {
125 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
126 ret = -1;
127 break;
132 return ret;
136 Session::process_routes (nframes_t nframes, bool& need_butler)
138 bool record_active;
139 int declick = get_transport_declick_required();
140 bool rec_monitors = get_rec_monitors_input();
141 boost::shared_ptr<RouteList> r = routes.reader ();
143 if (transport_sub_state & StopPendingCapture) {
144 /* force a declick out */
145 declick = -1;
148 record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
150 const nframes_t start_frame = _transport_frame;
151 const nframes_t end_frame = _transport_frame + (nframes_t)floor(nframes * _transport_speed);
153 route_graph->process_routes( nframes, start_frame, end_frame, declick, record_active, rec_monitors, need_butler);
155 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
157 int ret;
159 if ((*i)->is_hidden()) {
160 continue;
163 (*i)->set_pending_declick (declick);
165 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, rec_monitors, need_butler)) < 0) {
166 stop_transport ();
167 return -1;
171 return 0;
175 Session::silent_process_routes (nframes_t nframes, bool& need_butler)
177 bool record_active = actively_recording();
178 int declick = get_transport_declick_required();
179 bool rec_monitors = get_rec_monitors_input();
180 boost::shared_ptr<RouteList> r = routes.reader ();
182 if (transport_sub_state & StopPendingCapture) {
183 /* force a declick out */
184 declick = -1;
187 const nframes_t start_frame = _transport_frame;
188 const nframes_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
190 route_graph->silent_process_routes( nframes, start_frame, end_frame, record_active, rec_monitors, need_butler);
192 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
194 int ret;
196 if ((*i)->is_hidden()) {
197 continue;
200 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, rec_monitors, need_butler)) < 0) {
201 stop_transport ();
202 return -1;
206 return 0;
209 void
210 Session::get_track_statistics ()
212 float pworst = 1.0f;
213 float cworst = 1.0f;
215 boost::shared_ptr<RouteList> rl = routes.reader();
216 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
218 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
220 if (!tr || tr->hidden()) {
221 continue;
224 pworst = min (pworst, tr->playback_buffer_load());
225 cworst = min (cworst, tr->capture_buffer_load());
228 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
229 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
231 if (actively_recording()) {
232 set_dirty();
236 /** Process callback used when the auditioner is not active */
237 void
238 Session::process_with_events (nframes_t nframes)
240 SessionEvent* ev;
241 nframes_t this_nframes;
242 nframes_t end_frame;
243 bool session_needs_butler = false;
244 nframes_t stop_limit;
245 long frames_moved;
247 /* make sure the auditioner is silent */
249 if (auditioner) {
250 auditioner->silence (nframes);
253 /* handle any pending events */
255 while (pending_events.read (&ev, 1) == 1) {
256 merge_event (ev);
259 /* if we are not in the middle of a state change,
260 and there are immediate events queued up,
261 process them.
264 while (!non_realtime_work_pending() && !immediate_events.empty()) {
265 SessionEvent *ev = immediate_events.front ();
266 immediate_events.pop_front ();
267 process_event (ev);
270 /* Events caused a transport change, send an MTC Full Frame (Timecode) message.
271 * This is sent whether rolling or not, to give slaves an idea of ardour time
272 * on locates (and allow slow slaves to position and prepare for rolling)
274 if (_send_timecode_update) {
275 send_full_time_code(nframes);
278 if (!process_can_proceed()) {
279 _silent = true;
280 return;
283 if (events.empty() || next_event == events.end()) {
284 process_without_events (nframes);
285 return;
288 if (_transport_speed == 1.0) {
289 frames_moved = (long) nframes;
290 } else {
291 interpolation.set_target_speed (fabs(_target_transport_speed));
292 interpolation.set_speed (fabs(_transport_speed));
293 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
296 end_frame = _transport_frame + (nframes_t)frames_moved;
299 SessionEvent* this_event;
300 Events::iterator the_next_one;
302 if (!process_can_proceed()) {
303 _silent = true;
304 return;
307 if (!_exporting && _slave) {
308 if (!follow_slave (nframes)) {
309 return;
313 if (_transport_speed == 0) {
314 no_roll (nframes);
315 return;
318 if (!_exporting) {
319 send_midi_time_code_for_cycle (nframes);
322 if (actively_recording()) {
323 stop_limit = max_frames;
324 } else {
326 if (Config->get_stop_at_session_end()) {
327 stop_limit = current_end_frame();
328 } else {
329 stop_limit = max_frames;
333 if (maybe_stop (stop_limit)) {
334 no_roll (nframes);
335 return;
338 this_event = *next_event;
339 the_next_one = next_event;
340 ++the_next_one;
342 /* yes folks, here it is, the actual loop where we really truly
343 process some audio
346 while (nframes) {
348 this_nframes = nframes; /* real (jack) time relative */
349 frames_moved = (long) floor (_transport_speed * nframes); /* transport relative */
351 /* running an event, position transport precisely to its time */
352 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
353 /* this isn't quite right for reverse play */
354 frames_moved = (long) (this_event->action_frame - _transport_frame);
355 this_nframes = (nframes_t) abs( floor(frames_moved / _transport_speed) );
358 if (this_nframes) {
360 click (_transport_frame, this_nframes);
362 if (process_routes (this_nframes, session_needs_butler)) {
363 fail_roll (nframes);
364 return;
367 get_track_statistics ();
369 nframes -= this_nframes;
371 if (frames_moved < 0) {
372 decrement_transport_position (-frames_moved);
373 } else {
374 increment_transport_position (frames_moved);
377 maybe_stop (stop_limit);
378 check_declick_out ();
381 _engine.split_cycle (this_nframes);
383 /* now handle this event and all others scheduled for the same time */
385 while (this_event && this_event->action_frame == _transport_frame) {
386 process_event (this_event);
388 if (the_next_one == events.end()) {
389 this_event = 0;
390 } else {
391 this_event = *the_next_one;
392 ++the_next_one;
396 /* if an event left our state changing, do the right thing */
398 if (nframes && non_realtime_work_pending()) {
399 no_roll (nframes);
400 break;
403 /* this is necessary to handle the case of seamless looping */
404 end_frame = _transport_frame + (nframes_t) floor (nframes * _transport_speed);
408 set_next_event ();
410 } /* implicit release of route lock */
412 if (session_needs_butler) {
413 _butler->summon ();
417 void
418 Session::reset_slave_state ()
420 average_slave_delta = 1800;
421 delta_accumulator_cnt = 0;
422 have_first_delta_accumulator = false;
423 _slave_state = Stopped;
426 bool
427 Session::transport_locked () const
429 Slave* sl = _slave;
431 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
432 return true;
435 return false;
438 bool
439 Session::follow_slave (nframes_t nframes)
441 double slave_speed;
442 nframes64_t slave_transport_frame;
443 nframes_t this_delta;
444 int dir;
446 if (!_slave->ok()) {
447 stop_transport ();
448 config.set_external_sync (false);
449 goto noroll;
452 _slave->speed_and_position (slave_speed, slave_transport_frame);
454 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
456 if (!_slave->locked()) {
457 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
458 goto noroll;
461 if (slave_transport_frame > _transport_frame) {
462 this_delta = slave_transport_frame - _transport_frame;
463 dir = 1;
464 } else {
465 this_delta = _transport_frame - slave_transport_frame;
466 dir = -1;
469 if (_slave->starting()) {
470 slave_speed = 0.0f;
473 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
475 /* if the TC source is synced, then we assume that its
476 speed is binary: 0.0 or 1.0
479 if (slave_speed != 0.0f) {
480 slave_speed = 1.0f;
483 } else {
485 /* if we are chasing and the average delta between us and the
486 master gets too big, we want to switch to silent
487 motion. so keep track of that here.
490 if (_slave_state == Running) {
491 calculate_moving_average_of_slave_delta(dir, this_delta);
495 track_slave_state (slave_speed, slave_transport_frame, this_delta);
497 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
498 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
501 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
503 if (_transport_speed != 0.0f) {
506 note that average_dir is +1 or -1
509 float delta;
511 if (average_slave_delta == 0) {
512 delta = this_delta;
513 delta *= dir;
514 } else {
515 delta = average_slave_delta;
516 delta *= average_dir;
519 #ifndef NDEBUG
520 if (slave_speed != 0.0) {
521 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
522 (int) (dir * this_delta),
523 slave_speed,
524 _transport_speed,
525 _transport_frame,
526 slave_transport_frame,
527 average_slave_delta));
529 #endif
531 if (_slave->give_slave_full_control_over_transport_speed()) {
532 set_transport_speed (slave_speed, false, false);
533 //std::cout << "set speed = " << slave_speed << "\n";
534 } else {
535 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
536 request_transport_speed (adjusted_speed);
537 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
538 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
539 slave_speed));
542 #if 1
543 if ((nframes_t) abs(average_slave_delta) > _slave->resolution()) {
544 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
545 goto silent_motion;
547 #endif
552 if (_slave_state == Running && !non_realtime_work_pending()) {
553 /* speed is set, we're locked, and good to go */
554 return true;
557 silent_motion:
558 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
559 follow_slave_silently (nframes, slave_speed);
561 noroll:
562 /* don't move at all */
563 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
564 no_roll (nframes);
565 return false;
568 void
569 Session::calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta)
571 if (delta_accumulator_cnt >= delta_accumulator_size) {
572 have_first_delta_accumulator = true;
573 delta_accumulator_cnt = 0;
576 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
577 delta_accumulator[delta_accumulator_cnt++] = long(dir) * long(this_delta);
580 if (have_first_delta_accumulator) {
581 average_slave_delta = 0L;
582 for (int i = 0; i < delta_accumulator_size; ++i) {
583 average_slave_delta += delta_accumulator[i];
585 average_slave_delta /= long(delta_accumulator_size);
586 if (average_slave_delta < 0L) {
587 average_dir = -1;
588 average_slave_delta = abs(average_slave_delta);
589 } else {
590 average_dir = 1;
595 void
596 Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta)
598 if (slave_speed != 0.0f) {
600 /* slave is running */
602 switch (_slave_state) {
603 case Stopped:
604 if (_slave->requires_seekahead()) {
605 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
606 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
607 /* we can call locate() here because we are in process context */
608 locate (slave_wait_end, false, false);
609 _slave_state = Waiting;
611 } else {
613 _slave_state = Running;
615 Location* al = _locations.auto_loop_location();
617 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
618 // cancel looping
619 request_play_loop(false);
622 if (slave_transport_frame != _transport_frame) {
623 locate (slave_transport_frame, false, false);
626 break;
628 case Waiting:
629 default:
630 break;
633 if (_slave_state == Waiting) {
635 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
637 if (slave_transport_frame >= slave_wait_end) {
639 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
641 _slave_state = Running;
643 /* now perform a "micro-seek" within the disk buffers to realign ourselves
644 precisely with the master.
648 bool ok = true;
649 nframes_t frame_delta = slave_transport_frame - _transport_frame;
651 boost::shared_ptr<RouteList> rl = routes.reader();
652 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
653 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
654 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
655 ok = false;
656 break;
660 if (ok) {
661 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
662 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
663 if (tr) {
664 tr->internal_playback_seek (frame_delta);
667 _transport_frame += frame_delta;
669 } else {
670 cerr << "cannot micro-seek\n";
671 /* XXX what? */
674 memset (delta_accumulator, 0, sizeof (long) * delta_accumulator_size);
675 average_slave_delta = 0L;
676 this_delta = 0;
680 if (_slave_state == Running && _transport_speed == 0.0f) {
681 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
682 start_transport ();
685 } else { // slave_speed is 0
687 /* slave has stopped */
689 if (_transport_speed != 0.0f) {
690 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
691 stop_transport();
694 if (slave_transport_frame != _transport_frame) {
695 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
696 force_locate (slave_transport_frame, false);
699 _slave_state = Stopped;
703 void
704 Session::follow_slave_silently (nframes_t nframes, float slave_speed)
706 if (slave_speed && _transport_speed) {
708 /* something isn't right, but we should move with the master
709 for now.
712 bool need_butler;
714 silent_process_routes (nframes, need_butler);
716 get_track_statistics ();
718 if (need_butler) {
719 _butler->summon ();
722 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
724 if (frames_moved < 0) {
725 decrement_transport_position (-frames_moved);
726 } else {
727 increment_transport_position (frames_moved);
730 nframes_t stop_limit;
732 if (actively_recording()) {
733 stop_limit = max_frames;
734 } else {
735 if (Config->get_stop_at_session_end()) {
736 stop_limit = current_end_frame();
737 } else {
738 stop_limit = max_frames;
742 maybe_stop (stop_limit);
746 void
747 Session::process_without_events (nframes_t nframes)
749 bool session_needs_butler = false;
750 nframes_t stop_limit;
751 long frames_moved;
753 if (!process_can_proceed()) {
754 _silent = true;
755 return;
758 if (!_exporting && _slave) {
759 if (!follow_slave (nframes)) {
760 return;
764 if (_transport_speed == 0) {
765 fail_roll (nframes);
766 return;
769 if (!_exporting) {
770 send_midi_time_code_for_cycle (nframes);
773 if (actively_recording()) {
774 stop_limit = max_frames;
775 } else {
776 if (Config->get_stop_at_session_end()) {
777 stop_limit = current_end_frame();
778 } else {
779 stop_limit = max_frames;
783 if (maybe_stop (stop_limit)) {
784 fail_roll (nframes);
785 return;
788 if (maybe_sync_start (nframes)) {
789 return;
792 click (_transport_frame, nframes);
794 if (_transport_speed == 1.0) {
795 frames_moved = (long) nframes;
796 } else {
797 interpolation.set_target_speed (fabs(_target_transport_speed));
798 interpolation.set_speed (fabs(_transport_speed));
799 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
802 if (process_routes (nframes, session_needs_butler)) {
803 fail_roll (nframes);
804 return;
807 get_track_statistics ();
809 if (frames_moved < 0) {
810 decrement_transport_position (-frames_moved);
811 } else {
812 increment_transport_position (frames_moved);
815 maybe_stop (stop_limit);
816 check_declick_out ();
818 if (session_needs_butler) {
819 _butler->summon ();
823 /** Process callback used when the auditioner is active.
824 * @param nframes number of frames to process.
826 void
827 Session::process_audition (nframes_t nframes)
829 SessionEvent* ev;
830 boost::shared_ptr<RouteList> r = routes.reader ();
832 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
833 if (!(*i)->is_hidden()) {
834 (*i)->silence (nframes);
838 /* run the auditioner, and if it says we need butler service, ask for it */
840 if (auditioner->play_audition (nframes) > 0) {
841 _butler->summon ();
844 /* if using a monitor section, run it because otherwise we don't hear anything */
846 if (auditioner->needs_monitor()) {
847 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
850 /* handle pending events */
852 while (pending_events.read (&ev, 1) == 1) {
853 merge_event (ev);
856 /* if we are not in the middle of a state change,
857 and there are immediate events queued up,
858 process them.
861 while (!non_realtime_work_pending() && !immediate_events.empty()) {
862 SessionEvent *ev = immediate_events.front ();
863 immediate_events.pop_front ();
864 process_event (ev);
867 if (!auditioner->auditioning()) {
868 /* auditioner no longer active, so go back to the normal process callback */
869 process_function = &Session::process_with_events;
873 bool
874 Session::maybe_sync_start (nframes_t& nframes)
876 nframes_t sync_offset;
878 if (!waiting_for_sync_offset) {
879 return false;
882 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
884 /* generate silence up to the sync point, then
885 adjust nframes + offset to reflect whatever
886 is left to do.
889 no_roll (sync_offset);
890 nframes -= sync_offset;
891 Port::increment_port_offset (sync_offset);
892 waiting_for_sync_offset = false;
894 if (nframes == 0) {
895 return true; // done, nothing left to process
898 } else {
900 /* sync offset point is not within this process()
901 cycle, so just generate silence. and don't bother
902 with any fancy stuff here, just the minimal silence.
905 _silent = true;
907 if (Config->get_locate_while_waiting_for_sync()) {
908 if (micro_locate (nframes)) {
909 /* XXX ERROR !!! XXX */
913 return true; // done, nothing left to process
916 return false;
919 void
920 Session::queue_event (SessionEvent* ev)
922 if (_state_of_the_state & Deletion) {
923 return;
924 } else if (_state_of_the_state & Loading) {
925 merge_event (ev);
926 } else {
927 pending_events.write (&ev, 1);
931 void
932 Session::set_next_event ()
934 if (events.empty()) {
935 next_event = events.end();
936 return;
939 if (next_event == events.end()) {
940 next_event = events.begin();
943 if ((*next_event)->action_frame > _transport_frame) {
944 next_event = events.begin();
947 for (; next_event != events.end(); ++next_event) {
948 if ((*next_event)->action_frame >= _transport_frame) {
949 break;
954 void
955 Session::process_event (SessionEvent* ev)
957 bool remove = true;
958 bool del = true;
960 /* if we're in the middle of a state change (i.e. waiting
961 for the butler thread to complete the non-realtime
962 part of the change), we'll just have to queue this
963 event for a time when the change is complete.
966 if (non_realtime_work_pending()) {
968 /* except locates, which we have the capability to handle */
970 if (ev->type != SessionEvent::Locate) {
971 immediate_events.insert (immediate_events.end(), ev);
972 _remove_event (ev);
973 return;
977 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
979 switch (ev->type) {
980 case SessionEvent::SetLoop:
981 set_play_loop (ev->yes_or_no);
982 break;
984 case SessionEvent::AutoLoop:
985 if (play_loop) {
986 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
988 remove = false;
989 del = false;
990 break;
992 case SessionEvent::Locate:
993 if (ev->yes_or_no) {
994 // cerr << "forced locate to " << ev->target_frame << endl;
995 locate (ev->target_frame, false, true, false);
996 } else {
997 // cerr << "soft locate to " << ev->target_frame << endl;
998 start_locate (ev->target_frame, false, true, false);
1000 _send_timecode_update = true;
1001 break;
1003 case SessionEvent::LocateRoll:
1004 if (ev->yes_or_no) {
1005 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1006 locate (ev->target_frame, true, true, false);
1007 } else {
1008 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1009 start_locate (ev->target_frame, true, true, false);
1011 _send_timecode_update = true;
1012 break;
1014 case SessionEvent::LocateRollLocate:
1015 // locate is handled by ::request_roll_at_and_return()
1016 _requested_return_frame = ev->target_frame;
1017 request_locate (ev->target2_frame, true);
1018 break;
1021 case SessionEvent::SetTransportSpeed:
1022 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1023 break;
1025 case SessionEvent::PunchIn:
1026 // cerr << "PunchIN at " << transport_frame() << endl;
1027 if (config.get_punch_in() && record_status() == Enabled) {
1028 enable_record ();
1030 remove = false;
1031 del = false;
1032 break;
1034 case SessionEvent::PunchOut:
1035 // cerr << "PunchOUT at " << transport_frame() << endl;
1036 if (config.get_punch_out()) {
1037 step_back_from_record ();
1039 remove = false;
1040 del = false;
1041 break;
1043 case SessionEvent::StopOnce:
1044 if (!non_realtime_work_pending()) {
1045 stop_transport (ev->yes_or_no);
1046 _clear_event_type (SessionEvent::StopOnce);
1048 remove = false;
1049 del = false;
1050 break;
1052 case SessionEvent::RangeStop:
1053 if (!non_realtime_work_pending()) {
1054 stop_transport (ev->yes_or_no);
1056 remove = false;
1057 del = false;
1058 break;
1060 case SessionEvent::RangeLocate:
1061 start_locate (ev->target_frame, true, true, false);
1062 remove = false;
1063 del = false;
1064 break;
1066 case SessionEvent::Overwrite:
1067 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1068 break;
1070 case SessionEvent::SetTrackSpeed:
1071 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1072 break;
1074 case SessionEvent::SetSyncSource:
1075 use_sync_source (ev->slave);
1076 break;
1078 case SessionEvent::Audition:
1079 set_audition (ev->region);
1080 // drop reference to region
1081 ev->region.reset ();
1082 break;
1084 case SessionEvent::InputConfigurationChange:
1085 add_post_transport_work (PostTransportInputChange);
1086 _butler->schedule_transport_work ();
1087 break;
1089 case SessionEvent::SetPlayAudioRange:
1090 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1091 break;
1093 case SessionEvent::RealTimeOperation:
1094 process_rtop (ev);
1095 del = false; // other side of RT request needs to clean up
1096 break;
1098 case SessionEvent::AdjustPlaybackBuffering:
1099 schedule_playback_buffering_adjustment ();
1100 break;
1102 case SessionEvent::AdjustCaptureBuffering:
1103 schedule_capture_buffering_adjustment ();
1104 break;
1106 default:
1107 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1108 /*NOTREACHED*/
1109 break;
1112 if (remove) {
1113 del = del && !_remove_event (ev);
1116 if (del) {
1117 delete ev;