substantive change: use the JACK wait API and provide "thread buffers" separately...
[ardour.git] / libs / ardour / session_process.cc
1 /*
2     Copyright (C) 1999-2002 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #include <cmath>
21 #include <cerrno>
22 #include <algorithm>
23 #include <unistd.h>
24
25 #include "pbd/error.h"
26 #include "pbd/enumwriter.h"
27
28 #include <glibmm/thread.h>
29
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/process_thread.h"
37 #include "ardour/session.h"
38 #include "ardour/slave.h"
39 #include "ardour/timestamps.h"
40
41 #include "midi++/manager.h"
42
43 #include "i18n.h"
44
45 using namespace ARDOUR;
46 using namespace PBD;
47 using namespace std;
48
49 /** Called by the audio engine when there is work to be done with JACK.
50  * @param nframes Number of frames to process.
51  */
52 void
53 Session::process (nframes_t nframes)
54 {
55         MIDI::Manager::instance()->cycle_start(nframes);
56
57         _silent = false;
58
59         if (processing_blocked()) {
60                 _silent = true;
61                 return;
62         }
63
64         if (non_realtime_work_pending()) {
65                 if (!_butler->transport_work_requested ()) {
66                         post_transport ();
67                 }
68         }
69         
70         _engine.main_thread()->get_buffers ();
71
72         (this->*process_function) (nframes);
73
74         _engine.main_thread()->drop_buffers ();
75
76         // the ticker is for sending time information like MidiClock
77         nframes_t transport_frames = transport_frame();
78         BBT_Time  transport_bbt;
79         bbt_time(transport_frames, transport_bbt);
80         Timecode::Time transport_timecode;
81         timecode_time(transport_frames, transport_timecode);
82         tick (transport_frames, transport_bbt, transport_timecode); /* EMIT SIGNAL */
83
84         SendFeedback (); /* EMIT SIGNAL */
85
86         MIDI::Manager::instance()->cycle_end();
87 }
88
89 int
90 Session::fail_roll (nframes_t nframes)
91 {
92         return no_roll (nframes);
93 }
94
95 int
96 Session::no_roll (nframes_t nframes)
97 {
98         nframes_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
99         int ret = 0;
100         bool declick = get_transport_declick_required();
101         boost::shared_ptr<RouteList> r = routes.reader ();
102
103         if (_click_io) {
104                 _click_io->silence (nframes);
105         }
106
107         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
108
109                 if ((*i)->is_hidden()) {
110                         continue;
111                 }
112
113                 (*i)->set_pending_declick (declick);
114
115                 if ((*i)->no_roll (nframes, _transport_frame, end_frame, non_realtime_work_pending(),
116                                    actively_recording(), declick)) {
117                         error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
118                         ret = -1;
119                         break;
120                 }
121         }
122
123         return ret;
124 }
125
126 int
127 Session::process_routes (nframes_t nframes, bool& need_butler)
128 {
129         bool record_active;
130         int  declick = get_transport_declick_required();
131         bool rec_monitors = get_rec_monitors_input();
132         boost::shared_ptr<RouteList> r = routes.reader ();
133
134         if (transport_sub_state & StopPendingCapture) {
135                 /* force a declick out */
136                 declick = -1;
137         }
138
139         record_active = actively_recording(); // || (get_record_enabled() && get_punch_in());
140
141         const nframes_t start_frame = _transport_frame;
142         const nframes_t end_frame = _transport_frame + (nframes_t)floor(nframes * _transport_speed);
143
144         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
145
146                 int ret;
147
148                 if ((*i)->is_hidden()) {
149                         continue;
150                 }
151
152                 (*i)->set_pending_declick (declick);
153
154                 if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, rec_monitors, need_butler)) < 0) {
155                         stop_transport ();
156                         return -1;
157                 }
158         }
159
160         return 0;
161 }
162
163 int
164 Session::silent_process_routes (nframes_t nframes, bool& need_butler)
165 {
166         bool record_active = actively_recording();
167         int  declick = get_transport_declick_required();
168         bool rec_monitors = get_rec_monitors_input();
169         boost::shared_ptr<RouteList> r = routes.reader ();
170
171         if (transport_sub_state & StopPendingCapture) {
172                 /* force a declick out */
173                 declick = -1;
174         }
175
176         const nframes_t start_frame = _transport_frame;
177         const nframes_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
178
179         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
180
181                 int ret;
182
183                 if ((*i)->is_hidden()) {
184                         continue;
185                 }
186
187                 if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, rec_monitors, need_butler)) < 0) {
188                         stop_transport ();
189                         return -1;
190                 }
191         }
192
193         return 0;
194 }
195
196 void
197 Session::get_diskstream_statistics ()
198 {
199         float pworst = 1.0f;
200         float cworst = 1.0f;
201
202         boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
203         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
204
205                 if ((*i)->hidden()) {
206                         continue;
207                 }
208
209                 pworst = min (pworst, (*i)->playback_buffer_load());
210                 cworst = min (cworst, (*i)->capture_buffer_load());
211         }
212
213         uint32_t pmin = g_atomic_int_get (&_playback_load);
214         uint32_t pminold = g_atomic_int_get (&_playback_load_min);
215         uint32_t cmin = g_atomic_int_get (&_capture_load);
216         uint32_t cminold = g_atomic_int_get (&_capture_load_min);
217
218         g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
219         g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
220         g_atomic_int_set (&_playback_load_min, min (pmin, pminold));
221         g_atomic_int_set (&_capture_load_min, min (cmin, cminold));
222
223         if (actively_recording()) {
224                 set_dirty();
225         }
226 }
227
228 /** Process callback used when the auditioner is not active */
229 void
230 Session::process_with_events (nframes_t nframes)
231 {
232         SessionEvent*         ev;
233         nframes_t      this_nframes;
234         nframes_t      end_frame;
235         bool           session_needs_butler = false;
236         nframes_t      stop_limit;
237         long           frames_moved;
238
239         /* make sure the auditioner is silent */
240
241         if (auditioner) {
242                 auditioner->silence (nframes);
243         }
244
245         /* handle any pending events */
246
247         while (pending_events.read (&ev, 1) == 1) {
248                 merge_event (ev);
249         }
250
251         /* if we are not in the middle of a state change,
252            and there are immediate events queued up,
253            process them.
254         */
255
256         while (!non_realtime_work_pending() && !immediate_events.empty()) {
257                 SessionEvent *ev = immediate_events.front ();
258                 immediate_events.pop_front ();
259                 process_event (ev);
260         }
261
262         /* Events caused a transport change, send an MTC Full Frame (Timecode) message.
263          * This is sent whether rolling or not, to give slaves an idea of ardour time
264          * on locates (and allow slow slaves to position and prepare for rolling)
265          */
266         if (_send_timecode_update) {
267                 send_full_time_code(nframes);
268                 deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
269         }
270
271         if (!process_can_proceed()) {
272                 _silent = true;
273                 return;
274         }
275
276         if (events.empty() || next_event == events.end()) {
277                 process_without_events (nframes);
278                 return;
279         }
280
281         if (_transport_speed == 1.0) {
282                 frames_moved = (long) nframes;
283         } else {
284                 interpolation.set_target_speed (fabs(_target_transport_speed));
285                 interpolation.set_speed (fabs(_transport_speed));
286                 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
287         }
288
289         end_frame = _transport_frame + (nframes_t)frames_moved;
290
291         {
292                 SessionEvent* this_event;
293                 Events::iterator the_next_one;
294
295                 if (!process_can_proceed()) {
296                         _silent = true;
297                         return;
298                 }
299
300                 if (!_exporting && _slave) {
301                         if (!follow_slave (nframes)) {
302                                 return;
303                         }
304                 }
305
306                 if (_transport_speed == 0) {
307                         no_roll (nframes);
308                         return;
309                 }
310
311                 if (!_exporting) {
312                         send_midi_time_code_for_cycle (nframes);
313                 }
314
315                 if (actively_recording()) {
316                         stop_limit = max_frames;
317                 } else {
318
319                         if (Config->get_stop_at_session_end()) {
320                                 stop_limit = current_end_frame();
321                         } else {
322                                 stop_limit = max_frames;
323                         }
324                 }
325
326                 if (maybe_stop (stop_limit)) {
327                         no_roll (nframes);
328                         return;
329                 }
330
331                 this_event = *next_event;
332                 the_next_one = next_event;
333                 ++the_next_one;
334
335                 /* yes folks, here it is, the actual loop where we really truly
336                    process some audio
337                 */
338
339                 while (nframes) {
340
341                         this_nframes = nframes; /* real (jack) time relative */
342                         frames_moved = (long) floor (_transport_speed * nframes); /* transport relative */
343
344                         /* running an event, position transport precisely to its time */
345                         if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
346                                 /* this isn't quite right for reverse play */
347                                 frames_moved = (long) (this_event->action_frame - _transport_frame);
348                                 this_nframes = (nframes_t) abs( floor(frames_moved / _transport_speed) );
349                         }
350
351                         if (this_nframes) {
352
353                                 click (_transport_frame, this_nframes);
354
355                                 if (process_routes (this_nframes, session_needs_butler)) {
356                                         fail_roll (nframes);
357                                         return;
358                                 }
359
360                                 nframes -= this_nframes;
361
362                                 if (frames_moved < 0) {
363                                         decrement_transport_position (-frames_moved);
364                                 } else {
365                                         increment_transport_position (frames_moved);
366                                 }
367
368                                 maybe_stop (stop_limit);
369                                 check_declick_out ();
370                         }
371
372                         _engine.split_cycle (this_nframes);
373
374                         /* now handle this event and all others scheduled for the same time */
375
376                         while (this_event && this_event->action_frame == _transport_frame) {
377                                 process_event (this_event);
378
379                                 if (the_next_one == events.end()) {
380                                         this_event = 0;
381                                 } else {
382                                         this_event = *the_next_one;
383                                         ++the_next_one;
384                                 }
385                         }
386
387                         /* if an event left our state changing, do the right thing */
388
389                         if (nframes && non_realtime_work_pending()) {
390                                 no_roll (nframes);
391                                 break;
392                         }
393
394                         /* this is necessary to handle the case of seamless looping */
395                         end_frame = _transport_frame + (nframes_t) floor (nframes * _transport_speed);
396
397                 }
398
399                 set_next_event ();
400
401         } /* implicit release of route lock */
402
403         if (session_needs_butler) {
404                 _butler->summon ();
405         }
406 }
407
408 void
409 Session::reset_slave_state ()
410 {
411         average_slave_delta = 1800;
412         delta_accumulator_cnt = 0;
413         have_first_delta_accumulator = false;
414         _slave_state = Stopped;
415 }
416
417 bool
418 Session::transport_locked () const
419 {
420         Slave* sl = _slave;
421
422         if (!locate_pending() && (!config.get_external_sync() || (sl && sl->ok() && sl->locked()))) {
423                 return true;
424         }
425
426         return false;
427 }
428
429 bool
430 Session::follow_slave (nframes_t nframes)
431 {
432         double slave_speed;
433         nframes64_t slave_transport_frame;
434         nframes_t this_delta;
435         int dir;
436
437         if (!_slave->ok()) {
438                 stop_transport ();
439                 config.set_external_sync (false);
440                 goto noroll;
441         }
442
443         _slave->speed_and_position (slave_speed, slave_transport_frame);
444
445         DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
446
447         if (!_slave->locked()) {
448                 DEBUG_TRACE (DEBUG::Slave, "slave not locked\n");
449                 goto noroll;
450         }
451
452         if (slave_transport_frame > _transport_frame) {
453                 this_delta = slave_transport_frame - _transport_frame;
454                 dir = 1;
455         } else {
456                 this_delta = _transport_frame - slave_transport_frame;
457                 dir = -1;
458         }
459
460         if (_slave->starting()) {
461                 slave_speed = 0.0f;
462         }
463
464         if (_slave->is_always_synced() || config.get_timecode_source_is_synced()) {
465
466                 /* if the TC source is synced, then we assume that its
467                    speed is binary: 0.0 or 1.0
468                 */
469
470                 if (slave_speed != 0.0f) {
471                         slave_speed = 1.0f;
472                 }
473
474         } else {
475
476                 /* if we are chasing and the average delta between us and the
477                    master gets too big, we want to switch to silent
478                    motion. so keep track of that here.
479                 */
480
481                 if (_slave_state == Running) {
482                         calculate_moving_average_of_slave_delta(dir, this_delta);
483                 }
484         }
485
486         track_slave_state (slave_speed, slave_transport_frame, this_delta);
487
488         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave state %1 @ %2 speed %3 cur delta %4 avg delta %5\n",
489                                                    _slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
490                      
491
492         if (_slave_state == Running && !_slave->is_always_synced() && !config.get_timecode_source_is_synced()) {
493
494                 if (_transport_speed != 0.0f) {
495
496                         /*
497                            note that average_dir is +1 or -1
498                         */
499
500                         float delta;
501
502                         if (average_slave_delta == 0) {
503                                 delta = this_delta;
504                                 delta *= dir;
505                         } else {
506                                 delta = average_slave_delta;
507                                 delta *= average_dir;
508                         }
509
510 #ifndef NDEBUG
511                         if (slave_speed != 0.0) {
512                                 DEBUG_TRACE (DEBUG::Slave, string_compose ("delta = %1 speed = %2 ts = %3 M@%4 S@%5 avgdelta %6\n",
513                                                                            (int) (dir * this_delta),
514                                                                            slave_speed,
515                                                                            _transport_speed,
516                                                                            _transport_frame,
517                                                                            slave_transport_frame, 
518                                                                            average_slave_delta));
519                         }
520 #endif
521                         
522                         if (_slave->give_slave_full_control_over_transport_speed()) {
523                                 set_transport_speed (slave_speed, false, false);
524                                 //std::cout << "set speed = " << slave_speed << "\n";
525                         } else {
526                                 float adjusted_speed = slave_speed + (1.5 * (delta /  float(_current_frame_rate)));
527                                 request_transport_speed (adjusted_speed);
528                                 DEBUG_TRACE (DEBUG::Slave, string_compose ("adjust using %1 towards %2 ratio %3 current %4 slave @ %5\n",
529                                                                            delta, adjusted_speed, adjusted_speed/slave_speed, _transport_speed,
530                                                                            slave_speed));
531                         }
532                         
533 #if 1
534                         if ((nframes_t) abs(average_slave_delta) > _slave->resolution()) {
535                                 cerr << "average slave delta greater than slave resolution (" << _slave->resolution() << "), going to silent motion\n";
536                                 goto silent_motion;
537                         }
538 #endif
539                 }
540         }
541
542
543         if (_slave_state == Running && !non_realtime_work_pending()) {
544                 /* speed is set, we're locked, and good to go */
545                 return true;
546         }
547
548   silent_motion:
549         DEBUG_TRACE (DEBUG::Slave, "silent motion\n")
550         follow_slave_silently (nframes, slave_speed);
551
552   noroll:
553         /* don't move at all */
554         DEBUG_TRACE (DEBUG::Slave, "no roll\n")
555         no_roll (nframes);
556         return false;
557 }
558
559 void
560 Session::calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta)
561 {
562         if (delta_accumulator_cnt >= delta_accumulator_size) {
563                 have_first_delta_accumulator = true;
564                 delta_accumulator_cnt = 0;
565         }
566
567         if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
568                 delta_accumulator[delta_accumulator_cnt++] = long(dir) * long(this_delta);
569         }
570
571         if (have_first_delta_accumulator) {
572                 average_slave_delta = 0L;
573                 for (int i = 0; i < delta_accumulator_size; ++i) {
574                         average_slave_delta += delta_accumulator[i];
575                 }
576                 average_slave_delta /= long(delta_accumulator_size);
577                 if (average_slave_delta < 0L) {
578                         average_dir = -1;
579                         average_slave_delta = abs(average_slave_delta);
580                 } else {
581                         average_dir = 1;
582                 }
583         }
584 }
585
586 void
587 Session::track_slave_state (float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta)
588 {
589         if (slave_speed != 0.0f) {
590
591                 /* slave is running */
592
593                 switch (_slave_state) {
594                 case Stopped:
595                         if (_slave->requires_seekahead()) {
596                                 slave_wait_end = slave_transport_frame + _slave->seekahead_distance ();
597                                 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1\n", slave_wait_end));
598                                 /* we can call locate() here because we are in process context */
599                                 locate (slave_wait_end, false, false);
600                                 _slave_state = Waiting;
601
602                         } else {
603
604                                 _slave_state = Running;
605
606                                 Location* al = _locations.auto_loop_location();
607
608                                 if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) {
609                                         // cancel looping
610                                         request_play_loop(false);
611                                 }
612
613                                 if (slave_transport_frame != _transport_frame) {
614                                         locate (slave_transport_frame, false, false);
615                                 }
616                         }
617                         break;
618
619                 case Waiting:
620                 default:
621                         break;
622                 }
623
624                 if (_slave_state == Waiting) {
625
626                         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave waiting at %1\n", slave_transport_frame));
627
628                         if (slave_transport_frame >= slave_wait_end) {
629
630                                 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_frame, _transport_frame));
631
632                                 _slave_state = Running;
633
634                                 /* now perform a "micro-seek" within the disk buffers to realign ourselves
635                                    precisely with the master.
636                                 */
637
638
639                                 bool ok = true;
640                                 nframes_t frame_delta = slave_transport_frame - _transport_frame;
641
642                                 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
643
644                                 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
645                                         if (!(*i)->can_internal_playback_seek (frame_delta)) {
646                                                 ok = false;
647                                                 break;
648                                         }
649                                 }
650
651                                 if (ok) {
652                                         for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
653                                                 (*i)->internal_playback_seek (frame_delta);
654                                         }
655                                         _transport_frame += frame_delta;
656
657                                 } else {
658                                         cerr << "cannot micro-seek\n";
659                                         /* XXX what? */
660                                 }
661
662                                 memset (delta_accumulator, 0, sizeof (long) * delta_accumulator_size);
663                                 average_slave_delta = 0L;
664                                 this_delta = 0;
665                         }
666                 }
667
668                 if (_slave_state == Running && _transport_speed == 0.0f) {
669                         DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
670                         start_transport ();
671                 }
672
673         } else { // slave_speed is 0
674
675                 /* slave has stopped */
676
677                 if (_transport_speed != 0.0f) {
678                         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 frame %2 tf %3\n", slave_speed, slave_transport_frame, _transport_frame));
679                         stop_transport();
680                 }
681
682                 if (slave_transport_frame != _transport_frame) {
683                         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_frame));
684                         force_locate (slave_transport_frame, false);
685                 }
686
687                 _slave_state = Stopped;
688         }
689 }
690
691 void
692 Session::follow_slave_silently (nframes_t nframes, float slave_speed)
693 {
694         if (slave_speed && _transport_speed) {
695
696                 /* something isn't right, but we should move with the master
697                    for now.
698                 */
699
700                 bool need_butler;
701
702                 silent_process_routes (nframes, need_butler);
703
704                 if (need_butler) {
705                         _butler->summon ();
706                 }
707
708                 int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
709
710                 if (frames_moved < 0) {
711                         decrement_transport_position (-frames_moved);
712                 } else {
713                         increment_transport_position (frames_moved);
714                 }
715
716                 nframes_t stop_limit;
717
718                 if (actively_recording()) {
719                         stop_limit = max_frames;
720                 } else {
721                         if (Config->get_stop_at_session_end()) {
722                                 stop_limit = current_end_frame();
723                         } else {
724                                 stop_limit = max_frames;
725                         }
726                 }
727
728                 maybe_stop (stop_limit);
729         }
730 }
731
732 void
733 Session::process_without_events (nframes_t nframes)
734 {
735         bool session_needs_butler = false;
736         nframes_t stop_limit;
737         long frames_moved;
738
739         if (!process_can_proceed()) {
740                 _silent = true;
741                 return;
742         }
743
744         if (!_exporting && _slave) {
745                 if (!follow_slave (nframes)) {
746                         return;
747                 }
748         }
749
750         if (_transport_speed == 0) {
751                 fail_roll (nframes);
752                 return;
753         }
754
755         if (!_exporting) {
756                 send_midi_time_code_for_cycle (nframes);
757         }
758
759         if (actively_recording()) {
760                 stop_limit = max_frames;
761         } else {
762                 if (Config->get_stop_at_session_end()) {
763                         stop_limit = current_end_frame();
764                 } else {
765                         stop_limit = max_frames;
766                 }
767         }
768
769         if (maybe_stop (stop_limit)) {
770                 fail_roll (nframes);
771                 return;
772         }
773
774         if (maybe_sync_start (nframes)) {
775                 return;
776         }
777
778         click (_transport_frame, nframes);
779
780         if (_transport_speed == 1.0) {
781                 frames_moved = (long) nframes;
782         } else {
783                 interpolation.set_target_speed (fabs(_target_transport_speed));
784                 interpolation.set_speed (fabs(_transport_speed));
785                 frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
786         }
787
788         if (process_routes (nframes, session_needs_butler)) {
789                 fail_roll (nframes);
790                 return;
791         }
792
793         if (frames_moved < 0) {
794                 decrement_transport_position (-frames_moved);
795         } else {
796                 increment_transport_position (frames_moved);
797         }
798
799         maybe_stop (stop_limit);
800         check_declick_out ();
801
802         if (session_needs_butler) {
803                 _butler->summon ();
804         }
805 }
806
807 /** Process callback used when the auditioner is active.
808  * @param nframes number of frames to process.
809  */
810 void
811 Session::process_audition (nframes_t nframes)
812 {
813         SessionEvent* ev;
814         boost::shared_ptr<RouteList> r = routes.reader ();
815
816         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
817                 if (!(*i)->is_hidden()) {
818                         (*i)->silence (nframes);
819                 }
820         }
821
822         /* run the auditioner, and if it says we need butler service, ask for it */
823
824         if (auditioner->play_audition (nframes) > 0) {
825                 _butler->summon ();
826         }
827
828         /* if using a monitor section, run it because otherwise we don't hear anything */
829
830         if (auditioner->needs_monitor()) {
831                 _monitor_out->passthru (_transport_frame, _transport_frame + nframes, nframes, false);
832         }
833         
834         /* handle pending events */
835
836         while (pending_events.read (&ev, 1) == 1) {
837                 merge_event (ev);
838         }
839
840         /* if we are not in the middle of a state change,
841            and there are immediate events queued up,
842            process them.
843         */
844
845         while (!non_realtime_work_pending() && !immediate_events.empty()) {
846                 SessionEvent *ev = immediate_events.front ();
847                 immediate_events.pop_front ();
848                 process_event (ev);
849         }
850
851         if (!auditioner->auditioning()) {
852                 /* auditioner no longer active, so go back to the normal process callback */
853                 process_function = &Session::process_with_events;
854         }
855 }
856
857 bool
858 Session::maybe_sync_start (nframes_t& nframes)
859 {
860         nframes_t sync_offset;
861
862         if (!waiting_for_sync_offset) {
863                 return false;
864         }
865
866         if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
867
868                 /* generate silence up to the sync point, then
869                    adjust nframes + offset to reflect whatever
870                    is left to do.
871                 */
872
873                 no_roll (sync_offset);
874                 nframes -= sync_offset;
875                 Port::increment_port_offset (sync_offset);
876                 waiting_for_sync_offset = false;
877
878                 if (nframes == 0) {
879                         return true; // done, nothing left to process
880                 }
881
882         } else {
883
884                 /* sync offset point is not within this process()
885                    cycle, so just generate silence. and don't bother
886                    with any fancy stuff here, just the minimal silence.
887                 */
888
889                 _silent = true;
890
891                 if (Config->get_locate_while_waiting_for_sync()) {
892                         if (micro_locate (nframes)) {
893                                 /* XXX ERROR !!! XXX */
894                         }
895                 }
896
897                 return true; // done, nothing left to process
898         }
899
900         return false;
901 }
902
903 void
904 Session::queue_event (SessionEvent* ev)
905 {
906         if (_state_of_the_state & Deletion) {
907                 return;
908         } else if (_state_of_the_state & Loading) {
909                 merge_event (ev);
910         } else {
911                 pending_events.write (&ev, 1);
912         }
913 }
914
915 void
916 Session::set_next_event ()
917 {
918         if (events.empty()) {
919                 next_event = events.end();
920                 return;
921         }
922
923         if (next_event == events.end()) {
924                 next_event = events.begin();
925         }
926
927         if ((*next_event)->action_frame > _transport_frame) {
928                 next_event = events.begin();
929         }
930
931         for (; next_event != events.end(); ++next_event) {
932                 if ((*next_event)->action_frame >= _transport_frame) {
933                         break;
934                 }
935         }
936 }
937
938 void
939 Session::process_event (SessionEvent* ev)
940 {
941         bool remove = true;
942         bool del = true;
943
944         /* if we're in the middle of a state change (i.e. waiting
945            for the butler thread to complete the non-realtime
946            part of the change), we'll just have to queue this
947            event for a time when the change is complete.
948         */
949
950         if (non_realtime_work_pending()) {
951
952                 /* except locates, which we have the capability to handle */
953
954                 if (ev->type != SessionEvent::Locate) {
955                         immediate_events.insert (immediate_events.end(), ev);
956                         _remove_event (ev);
957                         return;
958                 }
959         }
960
961         DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_frame));
962
963         switch (ev->type) {
964         case SessionEvent::SetLoop:
965                 set_play_loop (ev->yes_or_no);
966                 break;
967
968         case SessionEvent::AutoLoop:
969                 if (play_loop) {
970                         start_locate (ev->target_frame, true, false, Config->get_seamless_loop());
971                 }
972                 remove = false;
973                 del = false;
974                 break;
975
976         case SessionEvent::Locate:
977                 if (ev->yes_or_no) {
978                         // cerr << "forced locate to " << ev->target_frame << endl;
979                         locate (ev->target_frame, false, true, false);
980                 } else {
981                         // cerr << "soft locate to " << ev->target_frame << endl;
982                         start_locate (ev->target_frame, false, true, false);
983                 }
984                 _send_timecode_update = true;
985                 break;
986
987         case SessionEvent::LocateRoll:
988                 if (ev->yes_or_no) {
989                         // cerr << "forced locate to+roll " << ev->target_frame << endl;
990                         locate (ev->target_frame, true, true, false);
991                 } else {
992                         // cerr << "soft locate to+roll " << ev->target_frame << endl;
993                         start_locate (ev->target_frame, true, true, false);
994                 }
995                 _send_timecode_update = true;
996                 break;
997
998         case SessionEvent::LocateRollLocate:
999                 // locate is handled by ::request_roll_at_and_return()
1000                 _requested_return_frame = ev->target_frame;
1001                 request_locate (ev->target2_frame, true);
1002                 break;
1003
1004
1005         case SessionEvent::SetTransportSpeed:
1006                 set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
1007                 break;
1008
1009         case SessionEvent::PunchIn:
1010                 // cerr << "PunchIN at " << transport_frame() << endl;
1011                 if (config.get_punch_in() && record_status() == Enabled) {
1012                         enable_record ();
1013                 }
1014                 remove = false;
1015                 del = false;
1016                 break;
1017
1018         case SessionEvent::PunchOut:
1019                 // cerr << "PunchOUT at " << transport_frame() << endl;
1020                 if (config.get_punch_out()) {
1021                         step_back_from_record ();
1022                 }
1023                 remove = false;
1024                 del = false;
1025                 break;
1026
1027         case SessionEvent::StopOnce:
1028                 if (!non_realtime_work_pending()) {
1029                         stop_transport (ev->yes_or_no);
1030                         _clear_event_type (SessionEvent::StopOnce);
1031                 }
1032                 remove = false;
1033                 del = false;
1034                 break;
1035
1036         case SessionEvent::RangeStop:
1037                 if (!non_realtime_work_pending()) {
1038                         stop_transport (ev->yes_or_no);
1039                 }
1040                 remove = false;
1041                 del = false;
1042                 break;
1043
1044         case SessionEvent::RangeLocate:
1045                 start_locate (ev->target_frame, true, true, false);
1046                 remove = false;
1047                 del = false;
1048                 break;
1049
1050         case SessionEvent::Overwrite:
1051                 overwrite_some_buffers (static_cast<Diskstream*>(ev->ptr));
1052                 break;
1053
1054         case SessionEvent::SetDiskstreamSpeed:
1055                 set_diskstream_speed (static_cast<Diskstream*> (ev->ptr), ev->speed);
1056                 break;
1057
1058         case SessionEvent::SetSyncSource:
1059                 use_sync_source (ev->slave);
1060                 break;
1061
1062         case SessionEvent::Audition:
1063                 set_audition (ev->region);
1064                 // drop reference to region
1065                 ev->region.reset ();
1066                 break;
1067
1068         case SessionEvent::InputConfigurationChange:
1069                 add_post_transport_work (PostTransportInputChange);
1070                 _butler->schedule_transport_work ();
1071                 break;
1072
1073         case SessionEvent::SetPlayAudioRange:
1074                 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1075                 break;
1076
1077         case SessionEvent::RealTimeOperation:
1078                 process_rtop (ev);
1079                 del = false; // other side of RT request needs to clean up
1080                 break;
1081
1082         default:
1083           fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1084                 /*NOTREACHED*/
1085                 break;
1086         };
1087
1088         if (remove) {
1089                 del = del && !_remove_event (ev);
1090         }
1091
1092         if (del) {
1093                 delete ev;
1094         }
1095 }
1096