switch MIDI Clock slave code to use DEBUG_TRACE; don't make it require start/stop...
[ardour2.git] / libs / ardour / session_process.cc
blob9baa0aea9e81dc6657bb08c8ed3e82b42f0426f9
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 void
85 Session::prepare_diskstreams ()
87 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
88 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
89 (*i)->prepare ();
93 int
94 Session::fail_roll (nframes_t nframes)
96 return no_roll (nframes);
99 int
100 Session::no_roll (nframes_t nframes)
102 nframes_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
103 int ret = 0;
104 bool declick = get_transport_declick_required();
105 boost::shared_ptr<RouteList> r = routes.reader ();
107 if (_click_io) {
108 _click_io->silence (nframes);
111 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
113 if ((*i)->is_hidden()) {
114 continue;
117 (*i)->set_pending_declick (declick);
119 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending(),
120 actively_recording(), declick)) {
121 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
122 ret = -1;
123 break;
127 return ret;
131 Session::process_routes (nframes_t nframes)
133 bool record_active;
134 int declick = get_transport_declick_required();
135 bool rec_monitors = get_rec_monitors_input();
136 boost::shared_ptr<RouteList> r = routes.reader ();
138 if (transport_sub_state & StopPendingCapture) {
139 /* force a declick out */
140 declick = -1;
143 record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
145 const nframes_t start_frame = _transport_frame;
146 const nframes_t end_frame = _transport_frame + (nframes_t)floor(nframes * _transport_speed);
148 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
150 int ret;
152 if ((*i)->is_hidden()) {
153 continue;
156 (*i)->set_pending_declick (declick);
158 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, rec_monitors)) < 0) {
160 /* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
161 and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
162 call path, so make sure we release any outstanding locks here before we return failure.
165 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
166 for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) {
167 (*ids)->recover ();
170 stop_transport ();
171 return -1;
175 return 0;
179 Session::silent_process_routes (nframes_t nframes)
181 bool record_active = actively_recording();
182 int declick = get_transport_declick_required();
183 bool rec_monitors = get_rec_monitors_input();
184 boost::shared_ptr<RouteList> r = routes.reader ();
186 if (transport_sub_state & StopPendingCapture) {
187 /* force a declick out */
188 declick = -1;
191 const nframes_t start_frame = _transport_frame;
192 const nframes_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
194 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
196 int ret;
198 if ((*i)->is_hidden()) {
199 continue;
202 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, rec_monitors)) < 0) {
204 /* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
205 and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
206 call path, so make sure we release any outstanding locks here before we return failure.
209 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
210 for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) {
211 (*ids)->recover ();
214 stop_transport ();
215 return -1;
219 return 0;
222 void
223 Session::commit_diskstreams (nframes_t nframes, bool &needs_butler)
225 int dret;
226 float pworst = 1.0f;
227 float cworst = 1.0f;
229 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
230 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
232 if ((*i)->hidden()) {
233 continue;
236 /* force all diskstreams not handled by a Route to call do their stuff.
237 Note: the diskstreams that were handled by a route will just return zero
238 from this call, because they know they were processed. So in fact, this
239 also runs commit() for every diskstream.
242 if ((dret = (*i)->process (_transport_frame, nframes, actively_recording(), get_rec_monitors_input())) == 0) {
243 if ((*i)->commit (nframes)) {
244 needs_butler = true;
247 } else if (dret < 0) {
248 (*i)->recover();
251 pworst = min (pworst, (*i)->playback_buffer_load());
252 cworst = min (cworst, (*i)->capture_buffer_load());
255 uint32_t pmin = g_atomic_int_get (&_playback_load);
256 uint32_t pminold = g_atomic_int_get (&_playback_load_min);
257 uint32_t cmin = g_atomic_int_get (&_capture_load);
258 uint32_t cminold = g_atomic_int_get (&_capture_load_min);
260 g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
261 g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
262 g_atomic_int_set (&_playback_load_min, min (pmin, pminold));
263 g_atomic_int_set (&_capture_load_min, min (cmin, cminold));
265 if (actively_recording()) {
266 set_dirty();
270 /** Process callback used when the auditioner is not active */
271 void
272 Session::process_with_events (nframes_t nframes)
274 SessionEvent* ev;
275 nframes_t this_nframes;
276 nframes_t end_frame;
277 bool session_needs_butler = false;
278 nframes_t stop_limit;
279 long frames_moved;
281 /* make sure the auditioner is silent */
283 if (auditioner) {
284 auditioner->silence (nframes);
287 /* handle any pending events */
289 while (pending_events.read (&ev, 1) == 1) {
290 merge_event (ev);
293 /* if we are not in the middle of a state change,
294 and there are immediate events queued up,
295 process them.
298 while (!non_realtime_work_pending() && !immediate_events.empty()) {
299 SessionEvent *ev = immediate_events.front ();
300 immediate_events.pop_front ();
301 process_event (ev);
304 /* Events caused a transport change, send an MTC Full Frame (Timecode) message.
305 * This is sent whether rolling or not, to give slaves an idea of ardour time
306 * on locates (and allow slow slaves to position and prepare for rolling)
308 if (_send_timecode_update) {
309 send_full_time_code(nframes);
310 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
313 if (!process_can_proceed()) {
314 _silent = true;
315 return;
318 if (events.empty() || next_event == events.end()) {
319 process_without_events (nframes);
320 return;
323 if (_transport_speed == 1.0) {
324 frames_moved = (long) nframes;
325 } else {
326 interpolation.set_target_speed (fabs(_target_transport_speed));
327 interpolation.set_speed (fabs(_transport_speed));
328 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
331 end_frame = _transport_frame + (nframes_t)frames_moved;
334 SessionEvent* this_event;
335 Events::iterator the_next_one;
337 if (!process_can_proceed()) {
338 _silent = true;
339 return;
342 if (!_exporting && _slave) {
343 if (!follow_slave (nframes)) {
344 return;
348 if (_transport_speed == 0) {
349 no_roll (nframes);
350 return;
353 if (!_exporting) {
354 send_midi_time_code_for_cycle (nframes);
357 if (actively_recording()) {
358 stop_limit = max_frames;
359 } else {
361 if (Config->get_stop_at_session_end()) {
362 stop_limit = current_end_frame();
363 } else {
364 stop_limit = max_frames;
368 if (maybe_stop (stop_limit)) {
369 no_roll (nframes);
370 return;
373 this_event = *next_event;
374 the_next_one = next_event;
375 ++the_next_one;
377 /* yes folks, here it is, the actual loop where we really truly
378 process some audio
381 while (nframes) {
383 this_nframes = nframes; /* real (jack) time relative */
384 frames_moved = (long) floor (_transport_speed * nframes); /* transport relative */
386 /* running an event, position transport precisely to its time */
387 if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
388 /* this isn't quite right for reverse play */
389 frames_moved = (long) (this_event->action_frame - _transport_frame);
390 this_nframes = (nframes_t) abs( floor(frames_moved / _transport_speed) );
393 if (this_nframes) {
395 click (_transport_frame, this_nframes);
397 /* now process frames between now and the first event in this block */
398 prepare_diskstreams ();
400 if (process_routes (this_nframes)) {
401 fail_roll (nframes);
402 return;
405 commit_diskstreams (this_nframes, session_needs_butler);
407 nframes -= this_nframes;
409 if (frames_moved < 0) {
410 decrement_transport_position (-frames_moved);
411 } else {
412 increment_transport_position (frames_moved);
415 maybe_stop (stop_limit);
416 check_declick_out ();
419 _engine.split_cycle (this_nframes);
421 /* now handle this event and all others scheduled for the same time */
423 while (this_event && this_event->action_frame == _transport_frame) {
424 process_event (this_event);
426 if (the_next_one == events.end()) {
427 this_event = 0;
428 } else {
429 this_event = *the_next_one;
430 ++the_next_one;
434 /* if an event left our state changing, do the right thing */
436 if (nframes && non_realtime_work_pending()) {
437 no_roll (nframes);
438 break;
441 /* this is necessary to handle the case of seamless looping */
442 end_frame = _transport_frame + (nframes_t) floor (nframes * _transport_speed);
446 set_next_event ();
448 } /* implicit release of route lock */
450 if (session_needs_butler) {
451 _butler->summon ();
455 void
456 Session::reset_slave_state ()
458 average_slave_delta = 1800;
459 delta_accumulator_cnt = 0;
460 have_first_delta_accumulator = false;
461 _slave_state = Stopped;
464 bool
465 Session::transport_locked () const
467 Slave* sl = _slave;
469 if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
470 return true;
473 return false;
476 bool
477 Session::follow_slave (nframes_t nframes)
479 double slave_speed;
480 nframes64_t slave_transport_frame;
481 nframes_t this_delta;
482 int dir;
484 if (!_slave->ok()) {
485 stop_transport ();
486 config.set_external_sync (false);
487 goto noroll;
490 _slave->speed_and_position (slave_speed, slave_transport_frame);
492 DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
494 if (!_slave->locked()) {
495 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
496 goto noroll;
499 if (slave_transport_frame > _transport_frame) {
500 this_delta = slave_transport_frame - _transport_frame;
501 dir = 1;
502 } else {
503 this_delta = _transport_frame - slave_transport_frame;
504 dir = -1;
507 if (_slave->starting()) {
508 slave_speed = 0.0f;
511 if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
513 /* if the TC source is synced, then we assume that its
514 speed is binary: 0.0 or 1.0
517 if (slave_speed != 0.0f) {
518 slave_speed = 1.0f;
521 } else {
523 /* if we are chasing and the average delta between us and the
524 master gets too big, we want to switch to silent
525 motion. so keep track of that here.
528 if (_slave_state == Running) {
529 calculate_moving_average_of_slave_delta(dir, this_delta);
533 track_slave_state (slave_speed, slave_transport_frame, this_delta);
535 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
536 _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
539 if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
541 if (_transport_speed != 0.0f) {
544 note that average_dir is +1 or -1
547 float delta;
549 if (average_slave_delta == 0) {
550 delta = this_delta;
551 delta *= dir;
552 } else {
553 delta = average_slave_delta;
554 delta *= average_dir;
557 #ifndef NDEBUG
558 if (slave_speed != 0.0) {
559 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
560 (int) (dir * this_delta),
561 slave_speed,
562 _transport_speed,
563 _transport_frame,
564 slave_transport_frame,
565 average_slave_delta));
567 #endif
569 if (_slave->give_slave_full_control_over_transport_speed()) {
570 set_transport_speed (slave_speed, false, false);
571 //std::cout << "set speed = " << slave_speed << "\n";
572 } else {
573 float adjusted_speed = slave_speed + (1.5 * (delta / float(_current_frame_rate)));
574 request_transport_speed (adjusted_speed);
575 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
576 delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
577 slave_speed));
580 #if 1
581 if ((nframes_t) abs(average_slave_delta) > _slave->resolution()) {
582 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
583 goto silent_motion;
585 #endif
590 if (_slave_state == Running && !non_realtime_work_pending()) {
591 /* speed is set, we're locked, and good to go */
592 return true;
595 silent_motion:
596 DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
597 follow_slave_silently (nframes, slave_speed);
599 noroll:
600 /* don't move at all */
601 DEBUG_TRACE (DEBUG::Slave, "no roll\n")
602 no_roll (nframes);
603 return false;
606 void
607 Session::calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta)
609 if (delta_accumulator_cnt >= delta_accumulator_size) {
610 have_first_delta_accumulator = true;
611 delta_accumulator_cnt = 0;
614 if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
615 delta_accumulator[delta_accumulator_cnt++] = long(dir) * long(this_delta);
618 if (have_first_delta_accumulator) {
619 average_slave_delta = 0L;
620 for (int i = 0; i < delta_accumulator_size; ++i) {
621 average_slave_delta += delta_accumulator[i];
623 average_slave_delta /= long(delta_accumulator_size);
624 if (average_slave_delta < 0L) {
625 average_dir = -1;
626 average_slave_delta = abs(average_slave_delta);
627 } else {
628 average_dir = 1;
633 void
634 Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta)
636 if (slave_speed != 0.0f) {
638 /* slave is running */
640 switch (_slave_state) {
641 case Stopped:
642 if (_slave->requires_seekahead()) {
643 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
644 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
645 /* we can call locate() here because we are in process context */
646 locate (slave_wait_end, false, false);
647 _slave_state = Waiting;
649 } else {
651 _slave_state = Running;
653 Location* al = _locations.auto_loop_location();
655 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
656 // cancel looping
657 request_play_loop(false);
660 if (slave_transport_frame != _transport_frame) {
661 locate (slave_transport_frame, false, false);
664 break;
666 case Waiting:
667 default:
668 break;
671 if (_slave_state == Waiting) {
673 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
675 if (slave_transport_frame >= slave_wait_end) {
677 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
679 _slave_state = Running;
681 /* now perform a "micro-seek" within the disk buffers to realign ourselves
682 precisely with the master.
686 bool ok = true;
687 nframes_t frame_delta = slave_transport_frame - _transport_frame;
689 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
691 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
692 if (!(*i)->can_internal_playback_seek (frame_delta)) {
693 ok = false;
694 break;
698 if (ok) {
699 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
700 (*i)->internal_playback_seek (frame_delta);
702 _transport_frame += frame_delta;
704 } else {
705 cerr << "cannot micro-seek\n";
706 /* XXX what? */
709 memset (delta_accumulator, 0, sizeof (long) * delta_accumulator_size);
710 average_slave_delta = 0L;
711 this_delta = 0;
715 if (_slave_state == Running && _transport_speed == 0.0f) {
716 DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
717 start_transport ();
720 } else { // slave_speed is 0
722 /* slave has stopped */
724 if (_transport_speed != 0.0f) {
725 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
726 stop_transport();
729 if (slave_transport_frame != _transport_frame) {
730 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
731 force_locate (slave_transport_frame, false);
734 _slave_state = Stopped;
738 void
739 Session::follow_slave_silently (nframes_t nframes, float slave_speed)
741 if (slave_speed && _transport_speed) {
743 /* something isn't right, but we should move with the master
744 for now.
747 bool need_butler;
749 prepare_diskstreams ();
750 silent_process_routes (nframes);
751 commit_diskstreams (nframes, need_butler);
753 if (need_butler) {
754 _butler->summon ();
757 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
759 if (frames_moved < 0) {
760 decrement_transport_position (-frames_moved);
761 } else {
762 increment_transport_position (frames_moved);
765 nframes_t stop_limit;
767 if (actively_recording()) {
768 stop_limit = max_frames;
769 } else {
770 if (Config->get_stop_at_session_end()) {
771 stop_limit = current_end_frame();
772 } else {
773 stop_limit = max_frames;
777 maybe_stop (stop_limit);
781 void
782 Session::process_without_events (nframes_t nframes)
784 bool session_needs_butler = false;
785 nframes_t stop_limit;
786 long frames_moved;
788 if (!process_can_proceed()) {
789 _silent = true;
790 return;
793 if (!_exporting && _slave) {
794 if (!follow_slave (nframes)) {
795 return;
799 if (_transport_speed == 0) {
800 fail_roll (nframes);
801 return;
804 if (!_exporting) {
805 send_midi_time_code_for_cycle (nframes);
808 if (actively_recording()) {
809 stop_limit = max_frames;
810 } else {
811 if (Config->get_stop_at_session_end()) {
812 stop_limit = current_end_frame();
813 } else {
814 stop_limit = max_frames;
818 if (maybe_stop (stop_limit)) {
819 fail_roll (nframes);
820 return;
823 if (maybe_sync_start (nframes)) {
824 return;
827 click (_transport_frame, nframes);
829 prepare_diskstreams ();
831 if (_transport_speed == 1.0) {
832 frames_moved = (long) nframes;
833 } else {
834 interpolation.set_target_speed (fabs(_target_transport_speed));
835 interpolation.set_speed (fabs(_transport_speed));
836 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
839 if (process_routes (nframes)) {
840 fail_roll (nframes);
841 return;
844 commit_diskstreams (nframes, session_needs_butler);
846 if (frames_moved < 0) {
847 decrement_transport_position (-frames_moved);
848 } else {
849 increment_transport_position (frames_moved);
852 maybe_stop (stop_limit);
853 check_declick_out ();
855 if (session_needs_butler) {
856 _butler->summon ();
860 /** Process callback used when the auditioner is active.
861 * @param nframes number of frames to process.
863 void
864 Session::process_audition (nframes_t nframes)
866 SessionEvent* ev;
867 boost::shared_ptr<RouteList> r = routes.reader ();
869 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
870 if (!(*i)->is_hidden()) {
871 (*i)->silence (nframes);
875 /* run the auditioner, and if it says we need butler service, ask for it */
877 if (auditioner->play_audition (nframes) > 0) {
878 _butler->summon ();
881 /* handle pending events */
883 while (pending_events.read (&ev, 1) == 1) {
884 merge_event (ev);
887 /* if we are not in the middle of a state change,
888 and there are immediate events queued up,
889 process them.
892 while (!non_realtime_work_pending() && !immediate_events.empty()) {
893 SessionEvent *ev = immediate_events.front ();
894 immediate_events.pop_front ();
895 process_event (ev);
898 if (!auditioner->active()) {
899 /* auditioner no longer active, so go back to the normal process callback */
900 process_function = &Session::process_with_events;
904 bool
905 Session::maybe_sync_start (nframes_t& nframes)
907 nframes_t sync_offset;
909 if (!waiting_for_sync_offset) {
910 return false;
913 if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
915 /* generate silence up to the sync point, then
916 adjust nframes + offset to reflect whatever
917 is left to do.
920 no_roll (sync_offset);
921 nframes -= sync_offset;
922 Port::increment_port_offset (sync_offset);
923 waiting_for_sync_offset = false;
925 if (nframes == 0) {
926 return true; // done, nothing left to process
929 } else {
931 /* sync offset point is not within this process()
932 cycle, so just generate silence. and don't bother
933 with any fancy stuff here, just the minimal silence.
936 _silent = true;
938 if (Config->get_locate_while_waiting_for_sync()) {
939 if (micro_locate (nframes)) {
940 /* XXX ERROR !!! XXX */
944 return true; // done, nothing left to process
947 return false;
950 void
951 Session::queue_event (SessionEvent* ev)
953 if (_state_of_the_state & Deletion) {
954 return;
955 } else if (_state_of_the_state & Loading) {
956 merge_event (ev);
957 } else {
958 pending_events.write (&ev, 1);
962 void
963 Session::set_next_event ()
965 if (events.empty()) {
966 next_event = events.end();
967 return;
970 if (next_event == events.end()) {
971 next_event = events.begin();
974 if ((*next_event)->action_frame > _transport_frame) {
975 next_event = events.begin();
978 for (; next_event != events.end(); ++next_event) {
979 if ((*next_event)->action_frame >= _transport_frame) {
980 break;
985 void
986 Session::process_event (SessionEvent* ev)
988 bool remove = true;
989 bool del = true;
991 /* if we're in the middle of a state change (i.e. waiting
992 for the butler thread to complete the non-realtime
993 part of the change), we'll just have to queue this
994 event for a time when the change is complete.
997 if (non_realtime_work_pending()) {
999 /* except locates, which we have the capability to handle */
1001 if (ev->type != SessionEvent::Locate) {
1002 immediate_events.insert (immediate_events.end(), ev);
1003 _remove_event (ev);
1004 return;
1008 DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
1010 switch (ev->type) {
1011 case SessionEvent::SetLoop:
1012 set_play_loop (ev->yes_or_no);
1013 break;
1015 case SessionEvent::AutoLoop:
1016 if (play_loop) {
1017 start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
1019 remove = false;
1020 del = false;
1021 break;
1023 case SessionEvent::Locate:
1024 if (ev->yes_or_no) {
1025 // cerr << "forced locate to " << ev->target_frame << endl;
1026 locate (ev->target_frame, false, true, false);
1027 } else {
1028 // cerr << "soft locate to " << ev->target_frame << endl;
1029 start_locate (ev->target_frame, false, true, false);
1031 _send_timecode_update = true;
1032 break;
1034 case SessionEvent::LocateRoll:
1035 if (ev->yes_or_no) {
1036 // cerr << "forced locate to+roll " << ev->target_frame << endl;
1037 locate (ev->target_frame, true, true, false);
1038 } else {
1039 // cerr << "soft locate to+roll " << ev->target_frame << endl;
1040 start_locate (ev->target_frame, true, true, false);
1042 _send_timecode_update = true;
1043 break;
1045 case SessionEvent::LocateRollLocate:
1046 // locate is handled by ::request_roll_at_and_return()
1047 _requested_return_frame = ev->target_frame;
1048 request_locate (ev->target2_frame, true);
1049 break;
1052 case SessionEvent::SetTransportSpeed:
1053 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1054 break;
1056 case SessionEvent::PunchIn:
1057 // cerr << "PunchIN at " << transport_frame() << endl;
1058 if (config.get_punch_in() && record_status() == Enabled) {
1059 enable_record ();
1061 remove = false;
1062 del = false;
1063 break;
1065 case SessionEvent::PunchOut:
1066 // cerr << "PunchOUT at " << transport_frame() << endl;
1067 if (config.get_punch_out()) {
1068 step_back_from_record ();
1070 remove = false;
1071 del = false;
1072 break;
1074 case SessionEvent::StopOnce:
1075 if (!non_realtime_work_pending()) {
1076 stop_transport (ev->yes_or_no);
1077 _clear_event_type (SessionEvent::StopOnce);
1079 remove = false;
1080 del = false;
1081 break;
1083 case SessionEvent::RangeStop:
1084 if (!non_realtime_work_pending()) {
1085 stop_transport (ev->yes_or_no);
1087 remove = false;
1088 del = false;
1089 break;
1091 case SessionEvent::RangeLocate:
1092 start_locate (ev->target_frame, true, true, false);
1093 remove = false;
1094 del = false;
1095 break;
1097 case SessionEvent::Overwrite:
1098 overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
1099 break;
1101 case SessionEvent::SetDiskstreamSpeed:
1102 set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
1103 break;
1105 case SessionEvent::SetSyncSource:
1106 use_sync_source (ev->slave);
1107 break;
1109 case SessionEvent::Audition:
1110 set_audition (ev->region);
1111 // drop reference to region
1112 ev->region.reset ();
1113 break;
1115 case SessionEvent::InputConfigurationChange:
1116 add_post_transport_work (PostTransportInputChange);
1117 _butler->schedule_transport_work ();
1118 break;
1120 case SessionEvent::SetPlayAudioRange:
1121 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1122 break;
1124 case SessionEvent::RealTimeOperation:
1125 process_rtop (ev);
1126 del = false; // other side of RT request needs to clean up
1127 break;
1129 default:
1130 fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1131 /*NOTREACHED*/
1132 break;
1135 if (remove) {
1136 del = del && !_remove_event (ev);
1139 if (del) {
1140 delete ev;