Unused skeleton of the transport state-machine
[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 <boost/msm/back/state_machine.hpp>
26 #include <boost/msm/front/state_machine_def.hpp>
27
28 #include "pbd/error.h"
29 #include "pbd/enumwriter.h"
30
31 #include <glibmm/threads.h>
32
33 #include "ardour/audioengine.h"
34 #include "ardour/auditioner.h"
35 #include "ardour/butler.h"
36 #include "ardour/cycle_timer.h"
37 #include "ardour/debug.h"
38 #include "ardour/disk_reader.h"
39 #include "ardour/graph.h"
40 #include "ardour/port.h"
41 #include "ardour/process_thread.h"
42 #include "ardour/scene_changer.h"
43 #include "ardour/session.h"
44 #include "ardour/transport_master.h"
45 #include "ardour/transport_master_manager.h"
46 #include "ardour/ticker.h"
47 #include "ardour/types.h"
48 #include "ardour/vca.h"
49 #include "ardour/vca_manager.h"
50
51 #include "midi++/mmc.h"
52
53 #include "pbd/i18n.h"
54
55 using namespace ARDOUR;
56 using namespace PBD;
57 using namespace std;
58
59 /* state machine */
60 namespace msm = boost::msm;
61 namespace mpl = boost::mpl;
62
63 namespace TransportState
64 {
65         /* events */
66         struct play {};
67         struct stop {};
68
69         /* front-end: define the FSM structure  */
70         struct TransportFSM : public msm::front::state_machine_def<TransportFSM>
71         {
72
73                 /* FSM states */
74                 struct Stopped : public msm::front::state<>
75                 {
76                         template <class Event,class FSM> void
77                                 on_entry (Event const&, FSM&)
78                                 {
79                                         std::cout << "entering: Stopped" << std::endl;
80                                 }
81                         template <class Event,class FSM> void
82                                 on_exit (Event const&, FSM&)
83                                 {
84                                         std::cout << "leaving: Stopped" << std::endl;
85                                 }
86                 };
87
88                 struct Playing : public msm::front::state<>
89                 {
90                         template <class Event,class FSM> void
91                                 on_entry (Event const&, FSM&)
92                                 {
93                                         std::cout << "entering: Playing" << std::endl;
94                                 }
95
96                         template <class Event,class FSM> void
97                                 on_exit (Event const&, FSM&)
98                                 {
99                                         std::cout << "leaving: Playing" << std::endl;
100                                 }
101                 };
102
103                 /* the initial state */
104                 typedef Stopped initial_state;
105
106                 /* transition actions */
107                 void start_playback (play const&)
108                 {
109                         std::cout << "player::start_playback\n";
110                 }
111
112                 void stop_playback (stop const&)
113                 {
114                         std::cout << "player::stop_playback\n";
115                 }
116
117                 typedef TransportFSM _t; // makes transition table cleaner
118
119                 struct transition_table : mpl::vector<
120                         //      Start     Event         Next      Action                                 Guard
121                         //    +---------+-------------+---------+---------------------+----------------------+
122                         a_row < Stopped , play        , Playing , &_t::start_playback                        >,
123                          _row < Stopped , stop        , Stopped                                              >,
124                         //    +---------+-------------+---------+---------------------+----------------------+
125                         a_row < Playing , stop        , Stopped , &_t::stop_playback                         >
126                         //    +---------+-------------+---------+---------------------+----------------------+
127                         > {};
128         };
129
130         typedef msm::back::state_machine<TransportFSM> transport_fsm;
131
132         void test()
133         {
134                 transport_fsm t;
135                 t.start ();
136                 t.process_event (play());
137                 t.process_event (stop());
138                 t.stop();
139         }
140
141 };
142
143 /** Called by the audio engine when there is work to be done with JACK.
144  * @param nframes Number of samples to process.
145  */
146
147 void
148 Session::process (pframes_t nframes)
149 {
150         samplepos_t transport_at_start = _transport_sample;
151
152         _silent = false;
153
154         if (processing_blocked()) {
155                 _silent = true;
156                 return;
157         }
158
159         if (non_realtime_work_pending()) {
160                 if (!_butler->transport_work_requested ()) {
161                         post_transport ();
162                 }
163         }
164
165         _engine.main_thread()->get_buffers ();
166
167         (this->*process_function) (nframes);
168
169         /* realtime-safe meter-position and processor-order changes
170          *
171          * ideally this would be done in
172          * Route::process_output_buffers() but various functions
173          * callig it hold a _processor_lock reader-lock
174          */
175         boost::shared_ptr<RouteList> r = routes.reader ();
176         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
177                 if ((*i)->apply_processor_changes_rt()) {
178                         _rt_emit_pending = true;
179                 }
180         }
181         if (_rt_emit_pending) {
182                 if (!_rt_thread_active) {
183                         emit_route_signals ();
184                 }
185                 if (pthread_mutex_trylock (&_rt_emit_mutex) == 0) {
186                         pthread_cond_signal (&_rt_emit_cond);
187                         pthread_mutex_unlock (&_rt_emit_mutex);
188                         _rt_emit_pending = false;
189                 }
190         }
191
192         _engine.main_thread()->drop_buffers ();
193
194         /* deliver MIDI clock. Note that we need to use the transport sample
195          * position at the start of process(), not the value at the end of
196          * it. We may already have ticked() because of a transport state
197          * change, for example.
198          */
199
200         try {
201                 if (!_silent && !_engine.freewheeling() && Config->get_send_midi_clock() && (transport_speed() == 1.0f || transport_speed() == 0.0f) && midi_clock->has_midi_port()) {
202                         midi_clock->tick (transport_at_start, nframes);
203                 }
204
205                 _scene_changer->run (transport_at_start, transport_at_start + nframes);
206
207         } catch (...) {
208                 /* don't bother with a message */
209         }
210
211         SendFeedback (); /* EMIT SIGNAL */
212 }
213
214 int
215 Session::fail_roll (pframes_t nframes)
216 {
217         return no_roll (nframes);
218 }
219
220 int
221 Session::no_roll (pframes_t nframes)
222 {
223         PT_TIMING_CHECK (4);
224
225         samplepos_t end_sample = _transport_sample + nframes; // FIXME: varispeed + no_roll ??
226         int ret = 0;
227         boost::shared_ptr<RouteList> r = routes.reader ();
228
229         if (_click_io) {
230                 _click_io->silence (nframes);
231         }
232
233         ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
234
235         VCAList v = _vca_manager->vcas ();
236         for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
237                 (*i)->automation_run (_transport_sample, nframes);
238         }
239
240         if (_process_graph) {
241                 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
242                 _process_graph->routes_no_roll( nframes, _transport_sample, end_sample, non_realtime_work_pending());
243         } else {
244                 PT_TIMING_CHECK (10);
245                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
246
247                         if ((*i)->is_auditioner()) {
248                                 continue;
249                         }
250
251                         if ((*i)->no_roll (nframes, _transport_sample, end_sample, non_realtime_work_pending())) {
252                                 error << string_compose(_("Session: error in no roll for %1"), (*i)->name()) << endmsg;
253                                 ret = -1;
254                                 break;
255                         }
256                 }
257                 PT_TIMING_CHECK (11);
258         }
259
260         PT_TIMING_CHECK (5);
261         return ret;
262 }
263
264 /** @param need_butler to be set to true by this method if it needs the butler,
265  *  otherwise it must be left alone.
266  */
267 int
268 Session::process_routes (pframes_t nframes, bool& need_butler)
269 {
270         boost::shared_ptr<RouteList> r = routes.reader ();
271
272         const samplepos_t start_sample = _transport_sample;
273         const samplepos_t end_sample = _transport_sample + floor (nframes * _transport_speed);
274
275         VCAList v = _vca_manager->vcas ();
276         for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
277                 (*i)->automation_run (start_sample, nframes);
278         }
279
280         _global_locate_pending = locate_pending ();
281
282         if (_process_graph) {
283                 DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
284                 if (_process_graph->process_routes (nframes, start_sample, end_sample, need_butler) < 0) {
285                         stop_transport ();
286                         return -1;
287                 }
288         } else {
289
290                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
291
292                         int ret;
293
294                         if ((*i)->is_auditioner()) {
295                                 continue;
296                         }
297
298                         bool b = false;
299
300                         if ((ret = (*i)->roll (nframes, start_sample, end_sample, b)) < 0) {
301                                 stop_transport ();
302                                 return -1;
303                         }
304
305                         if (b) {
306                                 DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 rolled and needs butler\n", (*i)->name()));
307                                 need_butler = true;
308                         }
309                 }
310         }
311
312         return 0;
313 }
314
315 void
316 Session::get_track_statistics ()
317 {
318         float pworst = 1.0f;
319         float cworst = 1.0f;
320
321         boost::shared_ptr<RouteList> rl = routes.reader();
322         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
323
324                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
325
326                 if (!tr || tr->is_private_route()) {
327                         continue;
328                 }
329
330                 pworst = min (pworst, tr->playback_buffer_load());
331                 cworst = min (cworst, tr->capture_buffer_load());
332         }
333
334         g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
335         g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
336
337         if (actively_recording()) {
338                 set_dirty();
339         }
340 }
341
342 bool
343 Session::compute_audible_delta (samplepos_t& pos_and_delta) const
344 {
345         if (_transport_speed == 0.0 || _count_in_samples > 0 || _remaining_latency_preroll > 0) {
346                 /* cannot compute audible delta, because the session is
347                    generating silence that does not correspond to the timeline,
348                    but is instead filling playback buffers to manage latency
349                    alignment.
350                 */
351                 DEBUG_TRACE (DEBUG::Slave, string_compose ("still adjusting for latency (%1) and/or count-in (%2) or stopped %1\n", _remaining_latency_preroll, _count_in_samples, _transport_speed));
352                 return false;
353         }
354
355         pos_and_delta -= _transport_sample;
356         return true;
357 }
358
359 /** Process callback used when the auditioner is not active */
360 void
361 Session::process_with_events (pframes_t nframes)
362 {
363         PT_TIMING_CHECK (3);
364
365         SessionEvent*  ev;
366         pframes_t      this_nframes;
367         samplepos_t     end_sample;
368         bool           session_needs_butler = false;
369         samplecnt_t     samples_moved;
370
371         /* make sure the auditioner is silent */
372
373         if (auditioner) {
374                 auditioner->silence (nframes);
375         }
376
377         /* handle any pending events */
378
379         while (pending_events.read (&ev, 1) == 1) {
380                 merge_event (ev);
381         }
382
383         /* if we are not in the middle of a state change,
384            and there are immediate events queued up,
385            process them.
386         */
387
388         while (!non_realtime_work_pending() && !immediate_events.empty()) {
389                 SessionEvent *ev = immediate_events.front ();
390                 immediate_events.pop_front ();
391                 process_event (ev);
392         }
393         /* only count-in when going to roll at speed 1.0 */
394         if (_transport_speed != 1.0 && _count_in_samples > 0) {
395                 _count_in_samples = 0;
396         }
397         if (_transport_speed == 0.0) {
398                 _remaining_latency_preroll = 0;
399         }
400
401         assert (_count_in_samples == 0 || _remaining_latency_preroll == 0 || _count_in_samples == _remaining_latency_preroll);
402
403         DEBUG_TRACE (DEBUG::Transport, string_compose ("Running count in/latency preroll of %1 & %2\n", _count_in_samples, _remaining_latency_preroll));
404
405         while (_count_in_samples > 0 || _remaining_latency_preroll > 0) {
406                 samplecnt_t ns;
407
408                 if (_remaining_latency_preroll > 0) {
409                         ns = std::min ((samplecnt_t)nframes, _remaining_latency_preroll);
410                 } else {
411                         ns = std::min ((samplecnt_t)nframes, _count_in_samples);
412                 }
413
414                 boost::shared_ptr<RouteList> r = routes.reader ();
415                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
416                         samplecnt_t route_offset = (*i)->playback_latency ();
417                         if (_remaining_latency_preroll > route_offset + ns) {
418                                 /* route will no-roll for complete pre-roll cycle */
419                                 continue;
420                         }
421                         if (_remaining_latency_preroll > route_offset) {
422                                 /* route may need partial no-roll and partial roll from
423                                 * (_transport_sample - _remaining_latency_preroll) ..  +ns.
424                                 * shorten and split the cycle.
425                                 */
426                                 ns = std::min (ns, (_remaining_latency_preroll - route_offset));
427                         }
428                 }
429
430                 if (_count_in_samples > 0) {
431                         run_click (_transport_sample - _count_in_samples, ns);
432                         assert (_count_in_samples >= ns);
433                         _count_in_samples -= ns;
434                 }
435
436                 if (_remaining_latency_preroll > 0) {
437                         if (_count_in_samples == 0) {
438                                 click (_transport_sample - _remaining_latency_preroll, ns);
439                         }
440                         if (process_routes (ns, session_needs_butler)) {
441                                 fail_roll (ns);
442                         }
443                 } else {
444                         no_roll (ns);
445                 }
446
447                 if (_remaining_latency_preroll > 0) {
448                         assert (_remaining_latency_preroll >= ns);
449                         _remaining_latency_preroll -= ns;
450                 }
451
452                 nframes -= ns;
453
454                 /* process events.. */
455                 if (!events.empty() && next_event != events.end()) {
456                         SessionEvent* this_event = *next_event;
457                         Events::iterator the_next_one = next_event;
458                         ++the_next_one;
459
460                         while (this_event && this_event->action_sample == _transport_sample) {
461                                 process_event (this_event);
462                                 if (the_next_one == events.end()) {
463                                         this_event = 0;
464                                 } else {
465                                         this_event = *the_next_one;
466                                         ++the_next_one;
467                                 }
468                         }
469                         set_next_event ();
470                 }
471
472                 if (nframes == 0) {
473                         return;
474                 } else {
475                         _engine.split_cycle (ns);
476                 }
477         }
478
479         /* Decide on what to do with quarter-frame MTC during this cycle */
480
481         bool const was_sending_qf_mtc = _send_qf_mtc;
482         double const tolerance = Config->get_mtc_qf_speed_tolerance() / 100.0;
483
484         if (_transport_speed != 0) {
485                 _send_qf_mtc = (
486                         Config->get_send_mtc () &&
487                         _transport_speed >= (1 - tolerance) &&
488                         _transport_speed <= (1 + tolerance)
489                         );
490
491                 if (_send_qf_mtc && !was_sending_qf_mtc) {
492                         /* we will re-start quarter-frame MTC this cycle, so send a full update to set things up */
493                         _send_timecode_update = true;
494                 }
495
496                 if (Config->get_send_mtc() && !_send_qf_mtc && _pframes_since_last_mtc > (sample_rate () / 4)) {
497                         /* we're sending MTC, but we're not sending QF MTC at the moment, and it's been
498                            a quarter of a second since we sent anything at all, so send a full MTC update
499                            this cycle.
500                         */
501                         _send_timecode_update = true;
502                 }
503
504                 _pframes_since_last_mtc += nframes;
505         }
506
507         /* Events caused a transport change (or we re-started sending
508          * MTC), so send an MTC Full Frame (Timecode) message.  This
509          * is sent whether rolling or not, to give slaves an idea of
510          * ardour time on locates (and allow slow slaves to position
511          * and prepare for rolling)
512          */
513         if (_send_timecode_update) {
514                 send_full_time_code (_transport_sample, nframes);
515         }
516
517         if (!process_can_proceed()) {
518                 _silent = true;
519                 return;
520         }
521
522         if (events.empty() || next_event == events.end()) {
523                 try_run_lua (nframes); // also during export ?? ->move to process_without_events()
524                 /* lua scripts may inject events */
525                 while (_n_lua_scripts > 0 && pending_events.read (&ev, 1) == 1) {
526                         merge_event (ev);
527                 }
528                 if (events.empty() || next_event == events.end()) {
529                         process_without_events (nframes);
530                         return;
531                 }
532         }
533
534         assert (_transport_speed == 0 || _transport_speed == 1.0 || _transport_speed == -1.0);
535
536         samples_moved = (samplecnt_t) nframes * _transport_speed;
537         DEBUG_TRACE (DEBUG::Transport, string_compose ("plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
538
539         end_sample = _transport_sample + samples_moved;
540
541         {
542                 SessionEvent* this_event;
543                 Events::iterator the_next_one;
544
545                 if (!process_can_proceed()) {
546                         _silent = true;
547                         return;
548                 }
549
550                 if (!_exporting && config.get_external_sync()) {
551                         if (!follow_transport_master (nframes)) {
552                                 ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
553                                 return;
554                         }
555                 }
556
557                 if (_transport_speed == 0) {
558                         no_roll (nframes);
559                         return;
560                 }
561
562                 if (!_exporting && !timecode_transmission_suspended()) {
563                         send_midi_time_code_for_cycle (_transport_sample, end_sample, nframes);
564                 }
565
566                 ltc_tx_send_time_code_for_cycle (_transport_sample, end_sample, _target_transport_speed, _transport_speed, nframes);
567
568                 samplepos_t stop_limit = compute_stop_limit ();
569
570                 if (maybe_stop (stop_limit)) {
571                         no_roll (nframes);
572                         return;
573                 }
574
575                 this_event = *next_event;
576                 the_next_one = next_event;
577                 ++the_next_one;
578
579                 /* yes folks, here it is, the actual loop where we really truly
580                    process some audio
581                 */
582
583                 while (nframes) {
584
585                         this_nframes = nframes; /* real (jack) time relative */
586                         samples_moved = (samplecnt_t) floor (_transport_speed * nframes); /* transport relative */
587                         DEBUG_TRACE (DEBUG::Transport, string_compose ("sub-loop plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
588
589                         /* running an event, position transport precisely to its time */
590                         if (this_event && this_event->action_sample <= end_sample && this_event->action_sample >= _transport_sample) {
591                                 /* this isn't quite right for reverse play */
592                                 samples_moved = (samplecnt_t) (this_event->action_sample - _transport_sample);
593                                 DEBUG_TRACE (DEBUG::Transport, string_compose ("sub-loop2 plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
594                                 this_nframes = abs (floor(samples_moved / _transport_speed));
595                         }
596
597                         try_run_lua (this_nframes);
598
599                         if (this_nframes) {
600
601                                 click (_transport_sample, this_nframes);
602
603                                 if (process_routes (this_nframes, session_needs_butler)) {
604                                         fail_roll (nframes);
605                                         return;
606                                 }
607
608                                 get_track_statistics ();
609
610                                 nframes -= this_nframes;
611
612                                 if (samples_moved < 0) {
613                                         decrement_transport_position (-samples_moved);
614                                         DEBUG_TRACE (DEBUG::Transport, string_compose ("DEcrement transport by %1 to %2\n", samples_moved, _transport_sample));
615                                 } else if (samples_moved) {
616                                         increment_transport_position (samples_moved);
617                                         DEBUG_TRACE (DEBUG::Transport, string_compose ("INcrement transport by %1 to %2\n", samples_moved, _transport_sample));
618                                 } else {
619                                         DEBUG_TRACE (DEBUG::Transport, "no transport motion\n");
620                                 }
621
622                                 maybe_stop (stop_limit);
623                         }
624
625                         if (nframes > 0) {
626                                 _engine.split_cycle (this_nframes);
627                         }
628
629                         /* now handle this event and all others scheduled for the same time */
630
631                         while (this_event && this_event->action_sample == _transport_sample) {
632                                 process_event (this_event);
633
634                                 if (the_next_one == events.end()) {
635                                         this_event = 0;
636                                 } else {
637                                         this_event = *the_next_one;
638                                         ++the_next_one;
639                                 }
640                         }
641
642                         /* if an event left our state changing, do the right thing */
643
644                         if (nframes && non_realtime_work_pending()) {
645                                 no_roll (nframes);
646                                 break;
647                         }
648
649                         /* this is necessary to handle the case of seamless looping */
650                         end_sample = _transport_sample + floor (nframes * _transport_speed);
651                 }
652
653                 set_next_event ();
654
655         } /* implicit release of route lock */
656
657         if (session_needs_butler) {
658                 DEBUG_TRACE (DEBUG::Butler, "p-with-events: session needs butler, call it\n");
659                 _butler->summon ();
660         }
661 }
662
663 bool
664 Session::transport_locked () const
665 {
666         if (!locate_pending() && (!config.get_external_sync() || (transport_master()->ok() && transport_master()->locked()))) {
667                 return true;
668         }
669
670         return false;
671 }
672
673 void
674 Session::process_without_events (pframes_t nframes)
675 {
676         bool session_needs_butler = false;
677         samplecnt_t samples_moved;
678
679         if (!process_can_proceed()) {
680                 _silent = true;
681                 return;
682         }
683
684         if (!_exporting && config.get_external_sync()) {
685                 if (!follow_transport_master (nframes)) {
686                         ltc_tx_send_time_code_for_cycle (_transport_sample, _transport_sample, 0, 0 , nframes);
687                         return;
688                 }
689         }
690
691         assert (_transport_speed == 0 || _transport_speed == 1.0 || _transport_speed == -1.0);
692
693         if (_transport_speed == 0) {
694                 no_roll (nframes);
695                 return;
696         } else {
697                 samples_moved = (samplecnt_t) nframes * _transport_speed;
698                 DEBUG_TRACE (DEBUG::Transport, string_compose ("no-events, plan to move transport by %1 (%2 @ %3)\n", samples_moved, nframes, _transport_speed));
699         }
700
701         if (!_exporting && !timecode_transmission_suspended()) {
702                 send_midi_time_code_for_cycle (_transport_sample, _transport_sample + samples_moved, nframes);
703         }
704
705         ltc_tx_send_time_code_for_cycle (_transport_sample, _transport_sample + samples_moved, _target_transport_speed, _transport_speed, nframes);
706
707         samplepos_t const stop_limit = compute_stop_limit ();
708
709         if (maybe_stop (stop_limit)) {
710                 no_roll (nframes);
711                 return;
712         }
713
714         if (maybe_sync_start (nframes)) {
715                 return;
716         }
717
718         click (_transport_sample, nframes);
719
720         if (process_routes (nframes, session_needs_butler)) {
721                 fail_roll (nframes);
722                 return;
723         }
724
725         get_track_statistics ();
726
727         if (samples_moved < 0) {
728                 decrement_transport_position (-samples_moved);
729                 DEBUG_TRACE (DEBUG::Transport, string_compose ("DEcrement transport by %1 to %2\n", samples_moved, _transport_sample));
730         } else if (samples_moved) {
731                 increment_transport_position (samples_moved);
732                 DEBUG_TRACE (DEBUG::Transport, string_compose ("INcrement transport by %1 to %2\n", samples_moved, _transport_sample));
733         } else {
734                 DEBUG_TRACE (DEBUG::Transport, "no transport motion\n");
735         }
736
737         maybe_stop (stop_limit);
738
739         if (session_needs_butler) {
740                 DEBUG_TRACE (DEBUG::Butler, "p-without-events: session needs butler, call it\n");
741                 _butler->summon ();
742         }
743 }
744
745 /** Process callback used when the auditioner is active.
746  * @param nframes number of samples to process.
747  */
748 void
749 Session::process_audition (pframes_t nframes)
750 {
751         SessionEvent* ev;
752         boost::shared_ptr<RouteList> r = routes.reader ();
753
754         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
755                 if (!(*i)->is_auditioner()) {
756                         (*i)->silence (nframes);
757                 }
758         }
759
760         /* run the auditioner, and if it says we need butler service, ask for it */
761
762         if (auditioner->play_audition (nframes) > 0) {
763                 DEBUG_TRACE (DEBUG::Butler, "auditioner needs butler, call it\n");
764                 _butler->summon ();
765         }
766
767         /* if using a monitor section, run it because otherwise we don't hear anything */
768
769         if (_monitor_out && auditioner->needs_monitor()) {
770                 _monitor_out->monitor_run (_transport_sample, _transport_sample + nframes, nframes);
771         }
772
773         /* handle pending events */
774
775         while (pending_events.read (&ev, 1) == 1) {
776                 merge_event (ev);
777         }
778
779         /* if we are not in the middle of a state change,
780            and there are immediate events queued up,
781            process them.
782         */
783
784         while (!non_realtime_work_pending() && !immediate_events.empty()) {
785                 SessionEvent *ev = immediate_events.front ();
786                 immediate_events.pop_front ();
787                 process_event (ev);
788         }
789
790         if (!auditioner->auditioning()) {
791                 /* auditioner no longer active, so go back to the normal process callback */
792                 process_function = &Session::process_with_events;
793         }
794 }
795
796 bool
797 Session::maybe_sync_start (pframes_t & nframes)
798 {
799         pframes_t sync_offset;
800
801         if (!waiting_for_sync_offset) {
802                 return false;
803         }
804
805         if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
806
807                 /* generate silence up to the sync point, then
808                    adjust nframes + offset to reflect whatever
809                    is left to do.
810                 */
811
812                 no_roll (sync_offset);
813                 nframes -= sync_offset;
814                 Port::increment_global_port_buffer_offset (sync_offset);
815                 waiting_for_sync_offset = false;
816
817                 if (nframes == 0) {
818                         return true; // done, nothing left to process
819                 }
820
821         } else {
822
823                 /* sync offset point is not within this process()
824                    cycle, so just generate silence. and don't bother
825                    with any fancy stuff here, just the minimal silence.
826                 */
827
828                 _silent = true;
829
830                 if (Config->get_locate_while_waiting_for_sync()) {
831                         DEBUG_TRACE (DEBUG::Transport, "micro-locate while waiting for sync\n");
832                         if (micro_locate (nframes)) {
833                                 /* XXX ERROR !!! XXX */
834                         }
835                 }
836
837                 return true; // done, nothing left to process
838         }
839
840         return false;
841 }
842
843 void
844 Session::queue_event (SessionEvent* ev)
845 {
846         if (_state_of_the_state & Deletion) {
847                 return;
848         } else if (_state_of_the_state & Loading) {
849                 merge_event (ev);
850         } else {
851                 Glib::Threads::Mutex::Lock lm (rb_write_lock);
852                 pending_events.write (&ev, 1);
853         }
854 }
855
856 void
857 Session::set_next_event ()
858 {
859         if (events.empty()) {
860                 next_event = events.end();
861                 return;
862         }
863
864         if (next_event == events.end()) {
865                 next_event = events.begin();
866         }
867
868         if ((*next_event)->action_sample > _transport_sample) {
869                 next_event = events.begin();
870         }
871
872         for (; next_event != events.end(); ++next_event) {
873                 if ((*next_event)->action_sample >= _transport_sample) {
874                         break;
875                 }
876         }
877 }
878
879 void
880 Session::process_event (SessionEvent* ev)
881 {
882         bool remove = true;
883         bool del = true;
884
885         /* if we're in the middle of a state change (i.e. waiting
886            for the butler thread to complete the non-realtime
887            part of the change), we'll just have to queue this
888            event for a time when the change is complete.
889         */
890
891         if (non_realtime_work_pending()) {
892
893                 /* except locates, which we have the capability to handle */
894
895                 if (ev->type != SessionEvent::Locate) {
896                         immediate_events.insert (immediate_events.end(), ev);
897                         _remove_event (ev);
898                         return;
899                 }
900         }
901
902         DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("Processing event: %1 @ %2\n", enum_2_string (ev->type), _transport_sample));
903
904         switch (ev->type) {
905         case SessionEvent::SetLoop:
906                 set_play_loop (ev->yes_or_no, ev->speed);
907                 break;
908
909         case SessionEvent::AutoLoop:
910                 if (play_loop) {
911                         /* roll after locate, do not flush, set "with loop"
912                            true only if we are seamless looping
913                         */
914                         start_locate (ev->target_sample, true, false, Config->get_seamless_loop());
915                 }
916                 remove = false;
917                 del = false;
918                 break;
919
920         case SessionEvent::Locate:
921                 if (ev->yes_or_no) { /* force locate */
922                         /* args: do not roll after locate, do flush, not with loop */
923                         locate (ev->target_sample, false, true, false);
924                 } else {
925                         /* args: do not roll after locate, do flush, not with loop */
926                         start_locate (ev->target_sample, false, true, false);
927                 }
928                 _send_timecode_update = true;
929                 break;
930
931         case SessionEvent::LocateRoll:
932                 if (ev->yes_or_no) {
933                         /* args: roll after locate, do flush, not with loop */
934                         locate (ev->target_sample, true, true, false);
935                 } else {
936                         /* args: roll after locate, do flush, not with loop */
937                         start_locate (ev->target_sample, true, true, false);
938                 }
939                 _send_timecode_update = true;
940                 break;
941
942         case SessionEvent::Skip:
943                 if (Config->get_skip_playback()) {
944                         start_locate (ev->target_sample, true, true, false);
945                         _send_timecode_update = true;
946                 }
947                 remove = false;
948                 del = false;
949                 break;
950
951         case SessionEvent::LocateRollLocate:
952                 // locate is handled by ::request_roll_at_and_return()
953                 _requested_return_sample = ev->target_sample;
954                 request_locate (ev->target2_sample, true);
955                 break;
956
957
958         case SessionEvent::SetTransportSpeed:
959                 set_transport_speed (ev->speed, ev->target_sample, ev->yes_or_no, ev->second_yes_or_no, ev->third_yes_or_no);
960                 break;
961
962         case SessionEvent::SetTransportMaster:
963                 TransportMasterManager::instance().set_current (ev->transport_master);
964                 break;
965
966         case SessionEvent::PunchIn:
967                 // cerr << "PunchIN at " << transport_sample() << endl;
968                 if (config.get_punch_in() && record_status() == Enabled) {
969                         enable_record ();
970                 }
971                 remove = false;
972                 del = false;
973                 break;
974
975         case SessionEvent::PunchOut:
976                 // cerr << "PunchOUT at " << transport_sample() << endl;
977                 if (config.get_punch_out()) {
978                         step_back_from_record ();
979                 }
980                 remove = false;
981                 del = false;
982                 break;
983
984         case SessionEvent::StopOnce:
985                 if (!non_realtime_work_pending()) {
986                         _clear_event_type (SessionEvent::StopOnce);
987                         stop_transport (ev->yes_or_no);
988                 }
989                 remove = false;
990                 del = false;
991                 break;
992
993         case SessionEvent::RangeStop:
994                 if (!non_realtime_work_pending()) {
995                         stop_transport (ev->yes_or_no);
996                 }
997                 remove = false;
998                 del = false;
999                 break;
1000
1001         case SessionEvent::RangeLocate:
1002                 /* args: roll after locate, do flush, not with loop */
1003                 start_locate (ev->target_sample, true, true, false);
1004                 remove = false;
1005                 del = false;
1006                 break;
1007
1008         case SessionEvent::Overwrite:
1009                 overwrite_some_buffers (static_cast<Track*>(ev->ptr));
1010                 break;
1011
1012         case SessionEvent::Audition:
1013                 set_audition (ev->region);
1014                 // drop reference to region
1015                 ev->region.reset ();
1016                 break;
1017
1018         case SessionEvent::SetPlayAudioRange:
1019                 set_play_range (ev->audio_range, (ev->speed == 1.0f));
1020                 break;
1021
1022         case SessionEvent::CancelPlayAudioRange:
1023                 unset_play_range();
1024                 break;
1025
1026         case SessionEvent::RealTimeOperation:
1027                 process_rtop (ev);
1028                 del = false; // other side of RT request needs to clean up
1029                 break;
1030
1031         case SessionEvent::AdjustPlaybackBuffering:
1032                 schedule_playback_buffering_adjustment ();
1033                 break;
1034
1035         case SessionEvent::AdjustCaptureBuffering:
1036                 schedule_capture_buffering_adjustment ();
1037                 break;
1038
1039         case SessionEvent::SetTimecodeTransmission:
1040                 g_atomic_int_set (&_suspend_timecode_transmission, ev->yes_or_no ? 0 : 1);
1041                 break;
1042
1043         default:
1044           fatal << string_compose(_("Programming error: illegal event type in process_event (%1)"), ev->type) << endmsg;
1045                 abort(); /*NOTREACHED*/
1046                 break;
1047         };
1048
1049         if (remove) {
1050                 del = del && !_remove_event (ev);
1051         }
1052
1053         if (del) {
1054                 delete ev;
1055         }
1056 }
1057
1058 samplepos_t
1059 Session::compute_stop_limit () const
1060 {
1061         if (!Config->get_stop_at_session_end ()) {
1062                 return max_samplepos;
1063         }
1064
1065         if (config.get_external_sync()) {
1066                 return max_samplepos;
1067         }
1068
1069         bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
1070         bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
1071
1072         if (actively_recording ()) {
1073                 /* permanently recording */
1074                 return max_samplepos;
1075         } else if (punching_in && !punching_out) {
1076                 /* punching in but never out */
1077                 return max_samplepos;
1078         } else if (punching_in && punching_out && _locations->auto_punch_location()->end() > current_end_sample()) {
1079                 /* punching in and punching out after session end */
1080                 return max_samplepos;
1081         }
1082
1083         return current_end_sample ();
1084 }
1085
1086
1087
1088 /* dedicated thread for signal emission.
1089  *
1090  * while sending cross-thread signals from the process thread
1091  * is fine in general, PBD::Signal's use of boost::function and
1092  * boost:bind can produce a vast overhead which is not
1093  * acceptable for low latency.
1094  *
1095  * This works around the issue by moving the boost overhead
1096  * out of the RT thread. The overall load is probably higher but
1097  * the realtime thread remains unaffected.
1098  */
1099
1100 void
1101 Session::emit_route_signals ()
1102 {
1103         // TODO use RAII to allow using these signals in other places
1104         BatchUpdateStart(); /* EMIT SIGNAL */
1105         boost::shared_ptr<RouteList> r = routes.reader ();
1106         for (RouteList::const_iterator ci = r->begin(); ci != r->end(); ++ci) {
1107                 (*ci)->emit_pending_signals ();
1108         }
1109         BatchUpdateEnd(); /* EMIT SIGNAL */
1110 }
1111
1112 void
1113 Session::emit_thread_start ()
1114 {
1115         if (_rt_thread_active) {
1116                 return;
1117         }
1118         _rt_thread_active = true;
1119
1120         if (pthread_create (&_rt_emit_thread, NULL, emit_thread, this)) {
1121                 _rt_thread_active = false;
1122         }
1123 }
1124
1125 void
1126 Session::emit_thread_terminate ()
1127 {
1128         if (!_rt_thread_active) {
1129                 return;
1130         }
1131         _rt_thread_active = false;
1132
1133         if (pthread_mutex_lock (&_rt_emit_mutex) == 0) {
1134                 pthread_cond_signal (&_rt_emit_cond);
1135                 pthread_mutex_unlock (&_rt_emit_mutex);
1136         }
1137
1138         void *status;
1139         pthread_join (_rt_emit_thread, &status);
1140 }
1141
1142 void *
1143 Session::emit_thread (void *arg)
1144 {
1145         Session *s = static_cast<Session *>(arg);
1146         s->emit_thread_run ();
1147         pthread_exit (0);
1148         return 0;
1149 }
1150
1151 void
1152 Session::emit_thread_run ()
1153 {
1154         pthread_mutex_lock (&_rt_emit_mutex);
1155         while (_rt_thread_active) {
1156                 emit_route_signals();
1157                 pthread_cond_wait (&_rt_emit_cond, &_rt_emit_mutex);
1158         }
1159         pthread_mutex_unlock (&_rt_emit_mutex);
1160 }
1161
1162 bool
1163 Session::follow_transport_master (pframes_t nframes)
1164 {
1165         TransportMasterManager& tmm (TransportMasterManager::instance());
1166
1167         double slave_speed;
1168         samplepos_t slave_transport_sample;
1169         sampleoffset_t delta;
1170
1171         if (tmm.master_invalid_this_cycle()) {
1172                 DEBUG_TRACE (DEBUG::Slave, "session told not to use the transport master this cycle\n");
1173                 goto noroll;
1174         }
1175
1176         slave_speed = tmm.get_current_speed_in_process_context();
1177         slave_transport_sample = tmm.get_current_position_in_process_context ();
1178
1179         track_transport_master (slave_speed, slave_transport_sample);
1180
1181         /* transport sample may have been moved during ::track_transport_master() */
1182
1183         delta = _transport_sample - slave_transport_sample;
1184
1185         DEBUG_TRACE (DEBUG::Slave, string_compose ("session at %1, master at %2, delta: %3 res: %4\n", _transport_sample, slave_transport_sample, delta, tmm.current()->resolution()));
1186
1187         if (transport_master_tracking_state == Running) {
1188
1189                 if (!actively_recording() && abs (delta) > tmm.current()->resolution()) {
1190                         DEBUG_TRACE (DEBUG::Slave, string_compose ("current slave delta %1 greater than slave resolution %2\n", delta, tmm.current()->resolution()));
1191                         if (micro_locate (-delta) != 0) {
1192                                 DEBUG_TRACE (DEBUG::Slave, "micro-locate didn't work, set no disk output true\n");
1193
1194                                 /* run routes as normal, but no disk output */
1195                                 DiskReader::set_no_disk_output (true);
1196                         }
1197                         return true;
1198                 }
1199
1200                 if (transport_master_tracking_state == Running) {
1201                         /* speed is set, we're locked, and good to go */
1202                         DiskReader::set_no_disk_output (false);
1203                         return true;
1204                 }
1205         }
1206
1207   noroll:
1208         /* don't move at all */
1209         DEBUG_TRACE (DEBUG::Slave, "no roll\n")
1210         no_roll (nframes);
1211         return false;
1212 }
1213
1214 void
1215 Session::track_transport_master (float slave_speed, samplepos_t slave_transport_sample)
1216 {
1217         boost::shared_ptr<TransportMaster> master (TransportMasterManager::instance().current());
1218
1219         assert (master);
1220
1221         DEBUG_TRACE (DEBUG::Slave, string_compose ("session has master tracking state as %1\n", transport_master_tracking_state));
1222
1223         if (slave_speed != 0.0f) {
1224
1225                 /* slave is running */
1226
1227                 switch (transport_master_tracking_state) {
1228                 case Stopped:
1229                         master_wait_end = slave_transport_sample + worst_latency_preroll() + master->seekahead_distance ();
1230                         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, but running, requires seekahead to %1, now WAITING\n", master_wait_end));
1231                         /* we can call locate() here because we are in process context */
1232                         if (micro_locate (master_wait_end - _transport_sample) != 0) {
1233                                 locate (master_wait_end, false, false);
1234                         }
1235                         transport_master_tracking_state = Waiting;
1236
1237                 case Waiting:
1238                 default:
1239                         break;
1240                 }
1241
1242                 if (transport_master_tracking_state == Waiting) {
1243
1244                         DEBUG_TRACE (DEBUG::Slave, string_compose ("master currently at %1, waiting to pass %2\n", slave_transport_sample, master_wait_end));
1245
1246                         if (slave_transport_sample >= master_wait_end) {
1247
1248                                 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave start at %1 vs %2\n", slave_transport_sample, _transport_sample));
1249
1250                                 transport_master_tracking_state = Running;
1251
1252                                 /* now perform a "micro-seek" within the disk buffers to realign ourselves
1253                                    precisely with the master.
1254                                 */
1255
1256                                 if (micro_locate (slave_transport_sample - _transport_sample) != 0) {
1257                                         cerr << "cannot micro-seek\n";
1258                                         /* XXX what? */
1259                                 }
1260                         }
1261                 }
1262
1263                 if (transport_master_tracking_state == Running && _transport_speed == 0.0f) {
1264                         DEBUG_TRACE (DEBUG::Slave, "slave starts transport\n");
1265                         start_transport ();
1266                 }
1267
1268         } else { // slave_speed is 0
1269
1270                 /* slave has stopped */
1271
1272                 if (_transport_speed != 0.0f) {
1273                         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stops transport: %1 sample %2 tf %3\n", slave_speed, slave_transport_sample, _transport_sample));
1274                         stop_transport ();
1275                 }
1276
1277                 if (slave_transport_sample != _transport_sample) {
1278                         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave stopped, move to %1\n", slave_transport_sample));
1279                         force_locate (slave_transport_sample, false);
1280                 }
1281
1282                 reset_slave_state();
1283         }
1284 }
1285
1286 void
1287 Session::reset_slave_state ()
1288 {
1289         transport_master_tracking_state = Stopped;
1290         DiskReader::set_no_disk_output (false);
1291 }