fix up fwd/reverse stuff in semitone mode
[ardour2.git] / libs / ardour / session_process.cc
blob3736c535fb02890291b02fe0ec53a504e5ef1e14
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/audio_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.
55 void
56 Session::process (pframes_t nframes)
58 MIDI::Manager::instance()->cycle_start(nframes);
60 _silent = false;
62 if (processing_blocked()) {
63 _silent = true;
64 return;
67 if (non_realtime_work_pending()) {
68 if (!_butler->transport_work_requested ()) {
69 post_transport ();
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();
92 int
93 Session::fail_roll (pframes_t nframes)
95 return no_roll (nframes);
98 int
99 Session::no_roll (pframes_t nframes)
101 framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
102 int ret = 0;
103 bool declick = get_transport_declick_required();
104 boost::shared_ptr<RouteList> r = routes.reader ();
106 if (_click_io) {
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);
113 } else {
114 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
116 if ((*i)->is_hidden()) {
117 continue;
120 (*i)->set_pending_declick (declick);
122 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending(),
123 actively_recording(), declick)) {
124 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
125 ret = -1;
126 break;
131 return ret;
135 Session::process_routes (pframes_t nframes, bool& need_butler)
137 bool record_active;
138 int declick = get_transport_declick_required();
139 bool rec_monitors = get_rec_monitors_input();
140 boost::shared_ptr<RouteList> r = routes.reader ();
142 if (transport_sub_state & StopPendingCapture) {
143 /* force a declick out */
144 declick = -1;
147 record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
149 const framepos_t start_frame = _transport_frame;
150 const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
152 /* XXX this is hack to force use of the graph even if we are only
153 using 1 thread. its needed because otherwise when we remove
154 tracks, the graph never gets updated.
156 if (1 || route_graph->threads_in_use() > 0) {
157 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
158 route_graph->process_routes( nframes, start_frame, end_frame, declick, record_active, rec_monitors, need_butler);
159 } else {
161 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
163 int ret;
165 if ((*i)->is_hidden()) {
166 continue;
169 (*i)->set_pending_declick (declick);
171 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, rec_monitors, need_butler)) < 0) {
172 stop_transport ();
173 return -1;
178 return 0;
182 Session::silent_process_routes (pframes_t nframes, bool& need_butler)
184 bool record_active = actively_recording();
185 int declick = get_transport_declick_required();
186 bool rec_monitors = get_rec_monitors_input();
187 boost::shared_ptr<RouteList> r = routes.reader ();
189 if (transport_sub_state & StopPendingCapture) {
190 /* force a declick out */
191 declick = -1;
194 const framepos_t start_frame = _transport_frame;
195 const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
197 /* XXX this is hack to force use of the graph even if we are only
198 using 1 thread. its needed because otherwise when we remove
199 tracks, the graph never gets updated.
201 if (1 || route_graph->threads_in_use() > 0) {
202 route_graph->silent_process_routes( nframes, start_frame, end_frame, record_active, rec_monitors, need_butler);
203 } else {
204 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
206 int ret;
208 if ((*i)->is_hidden()) {
209 continue;
212 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, rec_monitors, need_butler)) < 0) {
213 stop_transport ();
214 return -1;
219 return 0;
222 void
223 Session::get_track_statistics ()
225 float pworst = 1.0f;
226 float cworst = 1.0f;
228 boost::shared_ptr<RouteList> rl = routes.reader();
229 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
231 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
233 if (!tr || tr->hidden()) {
234 continue;
237 pworst = min (pworst, tr->playback_buffer_load());
238 cworst = min (cworst, tr->capture_buffer_load());
241 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
242 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
244 if (actively_recording()) {
245 set_dirty();
249 /** Process callback used when the auditioner is not active */
250 void
251 Session::process_with_events (pframes_t nframes)
253 SessionEvent* ev;
254 pframes_t this_nframes;
255 framepos_t end_frame;
256 bool session_needs_butler = false;
257 framepos_t stop_limit;
258 framecnt_t frames_moved;
260 /* make sure the auditioner is silent */
262 if (auditioner) {
263 auditioner->silence (nframes);
266 /* handle any pending events */
268 while (pending_events.read (&ev, 1) == 1) {
269 merge_event (ev);
272 /* if we are not in the middle of a state change,
273 and there are immediate events queued up,
274 process them.
277 while (!non_realtime_work_pending() && !immediate_events.empty()) {
278 SessionEvent *ev = immediate_events.front ();
279 immediate_events.pop_front ();
280 process_event (ev);
283 /* Decide on what to do with quarter-frame MTC during this cycle */
285 bool const was_sending_qf_mtc = _send_qf_mtc;
286 double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
288 if (_transport_speed != 0) {
289 _send_qf_mtc = (
290 Config->get_send_mtc () &&
291 _transport_speed >= (1 - tolerance) &&
292 _transport_speed <= (1 + tolerance)
295 if (_send_qf_mtc && !was_sending_qf_mtc) {
296 /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
297 _send_timecode_update = true;
300 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (frame_rate () / 4)) {
301 /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
302 a quarter of a second since we sent anything at all, so send a full MTC update
303 this cycle.
305 _send_timecode_update = true;
308 _pframes_since_last_mtc += nframes;
311 /* Events caused a transport change (or we re-started sending
312 * MTC), so send an MTC Full Frame (Timecode) message. This
313 * is sent whether rolling or not, to give slaves an idea of
314 * ardour time on locates (and allow slow slaves to position
315 * and prepare for rolling)
317 if (_send_timecode_update) {
318 send_full_time_code (_transport_frame);
321 if (!process_can_proceed()) {
322 _silent = true;
323 return;
326 if (events.empty() || next_event == events.end()) {
327 process_without_events (nframes);
328 return;
331 if (_transport_speed == 1.0) {
332 frames_moved = (framecnt_t) nframes;
333 } else {
334 interpolation.set_target_speed (fabs(_target_transport_speed));
335 interpolation.set_speed (fabs(_transport_speed));
336 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
339 end_frame = _transport_frame + frames_moved;
342 SessionEvent* this_event;
343 Events::iterator the_next_one;
345 if (!process_can_proceed()) {
346 _silent = true;
347 return;
350 if (!_exporting && _slave) {
351 if (!follow_slave (nframes)) {
352 return;
356 if (_transport_speed == 0) {
357 no_roll (nframes);
358 return;
361 if (!_exporting && !timecode_transmission_suspended()) {
362 send_midi_time_code_for_cycle (_transport_frame, end_frame, nframes);
365 if (actively_recording()) {
366 stop_limit = max_framepos;
367 } else {
369 if (Config->get_stop_at_session_end()) {
370 stop_limit = current_end_frame();
371 } else {
372 stop_limit = max_framepos;
376 if (maybe_stop (stop_limit)) {
377 no_roll (nframes);
378 return;
381 this_event = *next_event;
382 the_next_one = next_event;
383 ++the_next_one;
385 /* yes folks, here it is, the actual loop where we really truly
386 process some audio
389 while (nframes) {
391 this_nframes = nframes; /* real (jack) time relative */
392 frames_moved = (framecnt_t) floor (_transport_speed * nframes); /* transport relative */
394 /* running an event, position transport precisely to its time */
395 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
396 /* this isn't quite right for reverse play */
397 frames_moved = (framecnt_t) (this_event->action_frame - _transport_frame);
398 this_nframes = abs (floor(frames_moved / _transport_speed));
401 if (this_nframes) {
403 click (_transport_frame, this_nframes);
405 if (process_routes (this_nframes, session_needs_butler)) {
406 fail_roll (nframes);
407 return;
410 get_track_statistics ();
412 nframes -= this_nframes;
414 if (frames_moved < 0) {
415 decrement_transport_position (-frames_moved);
416 } else {
417 increment_transport_position (frames_moved);
420 maybe_stop (stop_limit);
421 check_declick_out ();
424 _engine.split_cycle (this_nframes);
426 /* now handle this event and all others scheduled for the same time */
428 while (this_event && this_event->action_frame == _transport_frame) {
429 process_event (this_event);
431 if (the_next_one == events.end()) {
432 this_event = 0;
433 } else {
434 this_event = *the_next_one;
435 ++the_next_one;
439 /* if an event left our state changing, do the right thing */
441 if (nframes && non_realtime_work_pending()) {
442 no_roll (nframes);
443 break;
446 /* this is necessary to handle the case of seamless looping */
447 end_frame = _transport_frame + floor (nframes * _transport_speed);
450 set_next_event ();
452 } /* implicit release of route lock */
454 if (session_needs_butler) {
455 _butler->summon ();
459 void
460 Session::reset_slave_state ()
462 average_slave_delta = 1800;
463 delta_accumulator_cnt = 0;
464 have_first_delta_accumulator = false;
465 _slave_state = Stopped;
468 bool
469 Session::transport_locked () const
471 Slave* sl = _slave;
473 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
474 return true;
477 return false;
480 bool
481 Session::follow_slave (pframes_t nframes)
483 double slave_speed;
484 framepos_t slave_transport_frame;
485 framecnt_t this_delta;
486 int dir;
488 if (!_slave->ok()) {
489 stop_transport ();
490 config.set_external_sync (false);
491 goto noroll;
494 _slave->speed_and_position (slave_speed, slave_transport_frame);
496 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
498 if (!_slave->locked()) {
499 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
500 goto noroll;
503 if (slave_transport_frame > _transport_frame) {
504 this_delta = slave_transport_frame - _transport_frame;
505 dir = 1;
506 } else {
507 this_delta = _transport_frame - slave_transport_frame;
508 dir = -1;
511 if (_slave->starting()) {
512 slave_speed = 0.0f;
515 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
517 /* if the TC source is synced, then we assume that its
518 speed is binary: 0.0 or 1.0
521 if (slave_speed != 0.0f) {
522 slave_speed = 1.0f;
525 } else {
527 /* if we are chasing and the average delta between us and the
528 master gets too big, we want to switch to silent
529 motion. so keep track of that here.
532 if (_slave_state == Running) {
533 calculate_moving_average_of_slave_delta(dir, this_delta);
537 track_slave_state (slave_speed, slave_transport_frame, this_delta);
539 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
540 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
543 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
545 if (_transport_speed != 0.0f) {
548 note that average_dir is +1 or -1
551 float delta;
553 if (average_slave_delta == 0) {
554 delta = this_delta;
555 delta *= dir;
556 } else {
557 delta = average_slave_delta;
558 delta *= average_dir;
561 #ifndef NDEBUG
562 if (slave_speed != 0.0) {
563 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
564 (int) (dir * this_delta),
565 slave_speed,
566 _transport_speed,
567 _transport_frame,
568 slave_transport_frame,
569 average_slave_delta));
571 #endif
573 if (_slave->give_slave_full_control_over_transport_speed()) {
574 set_transport_speed (slave_speed, false, false);
575 //std::cout << "set speed = " << slave_speed << "\n";
576 } else {
577 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
578 request_transport_speed (adjusted_speed);
579 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
580 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
581 slave_speed));
584 #if 1
585 if ((framecnt_t) abs(average_slave_delta) > _slave->resolution()) {
586 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
587 goto silent_motion;
589 #endif
594 if (_slave_state == Running && !non_realtime_work_pending()) {
595 /* speed is set, we're locked, and good to go */
596 return true;
599 silent_motion:
600 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
601 follow_slave_silently (nframes, slave_speed);
603 noroll:
604 /* don't move at all */
605 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
606 no_roll (nframes);
607 return false;
610 void
611 Session::calculate_moving_average_of_slave_delta (int dir, framecnt_t this_delta)
613 if (delta_accumulator_cnt >= delta_accumulator_size) {
614 have_first_delta_accumulator = true;
615 delta_accumulator_cnt = 0;
618 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
619 delta_accumulator[delta_accumulator_cnt++] = (framecnt_t) dir * (framecnt_t) this_delta;
622 if (have_first_delta_accumulator) {
623 average_slave_delta = 0L;
624 for (int i = 0; i < delta_accumulator_size; ++i) {
625 average_slave_delta += delta_accumulator[i];
627 average_slave_delta /= (int32_t) delta_accumulator_size;
628 if (average_slave_delta < 0L) {
629 average_dir = -1;
630 average_slave_delta = abs(average_slave_delta);
631 } else {
632 average_dir = 1;
637 void
638 Session::track_slave_state (float slave_speed, framepos_t slave_transport_frame, framecnt_t this_delta)
640 if (slave_speed != 0.0f) {
642 /* slave is running */
644 switch (_slave_state) {
645 case Stopped:
646 if (_slave->requires_seekahead()) {
647 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
648 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
649 /* we can call locate() here because we are in process context */
650 locate (slave_wait_end, false, false);
651 _slave_state = Waiting;
653 } else {
655 _slave_state = Running;
657 Location* al = _locations->auto_loop_location();
659 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
660 // cancel looping
661 request_play_loop(false);
664 if (slave_transport_frame != _transport_frame) {
665 locate (slave_transport_frame, false, false);
668 break;
670 case Waiting:
671 default:
672 break;
675 if (_slave_state == Waiting) {
677 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
679 if (slave_transport_frame >= slave_wait_end) {
681 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
683 _slave_state = Running;
685 /* now perform a "micro-seek" within the disk buffers to realign ourselves
686 precisely with the master.
690 bool ok = true;
691 framecnt_t frame_delta = slave_transport_frame - _transport_frame;
693 boost::shared_ptr<RouteList> rl = routes.reader();
694 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
695 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
696 if (tr && !tr->can_internal_playback_seek (frame_delta)) {
697 ok = false;
698 break;
702 if (ok) {
703 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
704 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
705 if (tr) {
706 tr->internal_playback_seek (frame_delta);
709 _transport_frame += frame_delta;
711 } else {
712 cerr << "cannot micro-seek\n";
713 /* XXX what? */
716 memset (delta_accumulator, 0, sizeof (int32_t) * delta_accumulator_size);
717 average_slave_delta = 0L;
718 this_delta = 0;
722 if (_slave_state == Running && _transport_speed == 0.0f) {
723 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
724 start_transport ();
727 } else { // slave_speed is 0
729 /* slave has stopped */
731 if (_transport_speed != 0.0f) {
732 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
733 stop_transport ();
736 if (slave_transport_frame != _transport_frame) {
737 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
738 force_locate (slave_transport_frame, false);
741 _slave_state = Stopped;
745 void
746 Session::follow_slave_silently (pframes_t nframes, float slave_speed)
748 if (slave_speed && _transport_speed) {
750 /* something isn't right, but we should move with the master
751 for now.
754 bool need_butler;
756 silent_process_routes (nframes, need_butler);
758 get_track_statistics ();
760 if (need_butler) {
761 _butler->summon ();
764 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
766 if (frames_moved < 0) {
767 decrement_transport_position (-frames_moved);
768 } else {
769 increment_transport_position (frames_moved);
772 framepos_t stop_limit;
774 if (actively_recording()) {
775 stop_limit = max_framepos;
776 } else {
777 if (Config->get_stop_at_session_end()) {
778 stop_limit = current_end_frame();
779 } else {
780 stop_limit = max_framepos;
784 maybe_stop (stop_limit);
788 void
789 Session::process_without_events (pframes_t nframes)
791 bool session_needs_butler = false;
792 framepos_t stop_limit;
793 framecnt_t frames_moved;
795 if (!process_can_proceed()) {
796 _silent = true;
797 return;
800 if (!_exporting && _slave) {
801 if (!follow_slave (nframes)) {
802 return;
806 if (_transport_speed == 0) {
807 fail_roll (nframes);
808 return;
811 if (_transport_speed == 1.0) {
812 frames_moved = (framecnt_t) nframes;
813 } else {
814 interpolation.set_target_speed (fabs(_target_transport_speed));
815 interpolation.set_speed (fabs(_transport_speed));
816 frames_moved = (framecnt_t) interpolation.interpolate (0, nframes, 0, 0);
819 if (!_exporting && !timecode_transmission_suspended()) {
820 send_midi_time_code_for_cycle (_transport_frame, _transport_frame + frames_moved, nframes);
823 if (actively_recording()) {
824 stop_limit = max_framepos;
825 } else {
826 if (Config->get_stop_at_session_end()) {
827 stop_limit = current_end_frame();
828 } else {
829 stop_limit = max_framepos;
833 if (maybe_stop (stop_limit)) {
834 fail_roll (nframes);
835 return;
838 if (maybe_sync_start (nframes)) {
839 return;
842 click (_transport_frame, nframes);
844 if (process_routes (nframes, session_needs_butler)) {
845 fail_roll (nframes);
846 return;
849 get_track_statistics ();
851 /* XXX: I'm not sure whether this is correct, but at least it
852 matches process_with_events, so that this new frames_moved
853 is -ve when transport speed is -ve. This means that the
854 transport position is updated correctly when we are in
855 reverse. It seems a bit wrong that we're not using the
856 interpolator to compute this.
859 frames_moved = (framecnt_t) floor (_transport_speed * nframes);
861 if (frames_moved < 0) {
862 decrement_transport_position (-frames_moved);
863 } else {
864 increment_transport_position (frames_moved);
867 maybe_stop (stop_limit);
868 check_declick_out ();
870 if (session_needs_butler) {
871 _butler->summon ();
875 /** Process callback used when the auditioner is active.
876 * @param nframes number of frames to process.
878 void
879 Session::process_audition (pframes_t nframes)
881 SessionEvent* ev;
882 boost::shared_ptr<RouteList> r = routes.reader ();
884 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
885 if (!(*i)->is_hidden()) {
886 (*i)->silence (nframes);
890 /* run the auditioner, and if it says we need butler service, ask for it */
892 if (auditioner->play_audition (nframes) > 0) {
893 _butler->summon ();
896 /* if using a monitor section, run it because otherwise we don't hear anything */
898 if (auditioner->needs_monitor()) {
899 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
902 /* handle pending events */
904 while (pending_events.read (&ev, 1) == 1) {
905 merge_event (ev);
908 /* if we are not in the middle of a state change,
909 and there are immediate events queued up,
910 process them.
913 while (!non_realtime_work_pending() && !immediate_events.empty()) {
914 SessionEvent *ev = immediate_events.front ();
915 immediate_events.pop_front ();
916 process_event (ev);
919 if (!auditioner->auditioning()) {
920 /* auditioner no longer active, so go back to the normal process callback */
921 process_function = &Session::process_with_events;
925 bool
926 Session::maybe_sync_start (pframes_t & nframes)
928 pframes_t sync_offset;
930 if (!waiting_for_sync_offset) {
931 return false;
934 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
936 /* generate silence up to the sync point, then
937 adjust nframes + offset to reflect whatever
938 is left to do.
941 no_roll (sync_offset);
942 nframes -= sync_offset;
943 Port::increment_global_port_buffer_offset (sync_offset);
944 waiting_for_sync_offset = false;
946 if (nframes == 0) {
947 return true; // done, nothing left to process
950 } else {
952 /* sync offset point is not within this process()
953 cycle, so just generate silence. and don't bother
954 with any fancy stuff here, just the minimal silence.
957 _silent = true;
959 if (Config->get_locate_while_waiting_for_sync()) {
960 if (micro_locate (nframes)) {
961 /* XXX ERROR !!! XXX */
965 return true; // done, nothing left to process
968 return false;
971 void
972 Session::queue_event (SessionEvent* ev)
974 if (_state_of_the_state & Deletion) {
975 return;
976 } else if (_state_of_the_state & Loading) {
977 merge_event (ev);
978 } else {
979 pending_events.write (&ev, 1);
983 void
984 Session::set_next_event ()
986 if (events.empty()) {
987 next_event = events.end();
988 return;
991 if (next_event == events.end()) {
992 next_event = events.begin();
995 if ((*next_event)->action_frame > _transport_frame) {
996 next_event = events.begin();
999 for (; next_event != events.end(); ++next_event) {
1000 if ((*next_event)->action_frame >= _transport_frame) {
1001 break;
1006 void
1007 Session::process_event (SessionEvent* ev)
1009 bool remove = true;
1010 bool del = true;
1012 /* if we're in the middle of a state change (i.e. waiting
1013 for the butler thread to complete the non-realtime
1014 part of the change), we'll just have to queue this
1015 event for a time when the change is complete.
1018 if (non_realtime_work_pending()) {
1020 /* except locates, which we have the capability to handle */
1022 if (ev->type != SessionEvent::Locate) {
1023 immediate_events.insert (immediate_events.end(), ev);
1024 _remove_event (ev);
1025 return;
1029 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1031 switch (ev->type) {
1032 case SessionEvent::SetLoop:
1033 set_play_loop (ev->yes_or_no);
1034 break;
1036 case SessionEvent::AutoLoop:
1037 if (play_loop) {
1038 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1040 remove = false;
1041 del = false;
1042 break;
1044 case SessionEvent::Locate:
1045 if (ev->yes_or_no) {
1046 // cerr << "forced locate to " << ev->target_frame << endl;
1047 locate (ev->target_frame, false, true, false);
1048 } else {
1049 // cerr << "soft locate to " << ev->target_frame << endl;
1050 start_locate (ev->target_frame, false, true, false);
1052 _send_timecode_update = true;
1053 break;
1055 case SessionEvent::LocateRoll:
1056 if (ev->yes_or_no) {
1057 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1058 locate (ev->target_frame, true, true, false);
1059 } else {
1060 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1061 start_locate (ev->target_frame, true, true, false);
1063 _send_timecode_update = true;
1064 break;
1066 case SessionEvent::LocateRollLocate:
1067 // locate is handled by ::request_roll_at_and_return()
1068 _requested_return_frame = ev->target_frame;
1069 request_locate (ev->target2_frame, true);
1070 break;
1073 case SessionEvent::SetTransportSpeed:
1074 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1075 break;
1077 case SessionEvent::PunchIn:
1078 // cerr << "PunchIN at " << transport_frame() << endl;
1079 if (config.get_punch_in() && record_status() == Enabled) {
1080 enable_record ();
1082 remove = false;
1083 del = false;
1084 break;
1086 case SessionEvent::PunchOut:
1087 // cerr << "PunchOUT at " << transport_frame() << endl;
1088 if (config.get_punch_out()) {
1089 step_back_from_record ();
1091 remove = false;
1092 del = false;
1093 break;
1095 case SessionEvent::StopOnce:
1096 if (!non_realtime_work_pending()) {
1097 stop_transport (ev->yes_or_no);
1098 _clear_event_type (SessionEvent::StopOnce);
1100 remove = false;
1101 del = false;
1102 break;
1104 case SessionEvent::RangeStop:
1105 if (!non_realtime_work_pending()) {
1106 stop_transport (ev->yes_or_no);
1108 remove = false;
1109 del = false;
1110 break;
1112 case SessionEvent::RangeLocate:
1113 start_locate (ev->target_frame, true, true, false);
1114 remove = false;
1115 del = false;
1116 break;
1118 case SessionEvent::Overwrite:
1119 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1120 break;
1122 case SessionEvent::SetTrackSpeed:
1123 set_track_speed (static_cast<Track*> (ev->ptr), ev->speed);
1124 break;
1126 case SessionEvent::SetSyncSource:
1127 use_sync_source (ev->slave);
1128 break;
1130 case SessionEvent::Audition:
1131 set_audition (ev->region);
1132 // drop reference to region
1133 ev->region.reset ();
1134 break;
1136 case SessionEvent::InputConfigurationChange:
1137 add_post_transport_work (PostTransportInputChange);
1138 _butler->schedule_transport_work ();
1139 break;
1141 case SessionEvent::SetPlayAudioRange:
1142 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1143 break;
1145 case SessionEvent::RealTimeOperation:
1146 process_rtop (ev);
1147 del = false; // other side of RT request needs to clean up
1148 break;
1150 case SessionEvent::AdjustPlaybackBuffering:
1151 schedule_playback_buffering_adjustment ();
1152 break;
1154 case SessionEvent::AdjustCaptureBuffering:
1155 schedule_capture_buffering_adjustment ();
1156 break;
1158 case SessionEvent::SetTimecodeTransmission:
1159 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1160 break;
1162 default:
1163 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1164 /*NOTREACHED*/
1165 break;
1168 if (remove) {
1169 del = del && !_remove_event (ev);
1172 if (del) {
1173 delete ev;