Fairly major change to the way in which crossfades are handled;
[ardour.git] / libs / ardour / session_transport.cc
1 /*
2     Copyright (C) 1999-2003 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 <unistd.h>
23
24 #ifdef WAF_BUILD
25 #include "libardour-config.h"
26 #endif
27
28
29 #include "pbd/undo.h"
30 #include "pbd/error.h"
31 #include "pbd/enumwriter.h"
32 #include "pbd/pthread_utils.h"
33 #include "pbd/memento_command.h"
34
35 #include "midi++/mmc.h"
36 #include "midi++/port.h"
37 #include "midi++/manager.h"
38
39 #include "ardour/ardour.h"
40 #include "ardour/audioengine.h"
41 #include "ardour/auditioner.h"
42 #include "ardour/butler.h"
43 #include "ardour/click.h"
44 #include "ardour/debug.h"
45 #include "ardour/location.h"
46 #include "ardour/session.h"
47 #include "ardour/slave.h"
48 #include "ardour/operations.h"
49
50 #include "i18n.h"
51
52 using namespace std;
53 using namespace ARDOUR;
54 using namespace PBD;
55
56 void
57 Session::add_post_transport_work (PostTransportWork ptw)
58 {
59         PostTransportWork oldval;
60         PostTransportWork newval;
61         int tries = 0;
62
63         while (tries < 8) {
64                 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
65                 newval = PostTransportWork (oldval | ptw);
66                 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
67                         /* success */
68                         return;
69                 }
70         }
71
72         error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
73 }
74
75 void
76 Session::request_input_change_handling ()
77 {
78         if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
79                 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
80                 queue_event (ev);
81         }
82 }
83
84 void
85 Session::request_sync_source (Slave* new_slave)
86 {
87         SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
88         bool seamless;
89
90         seamless = Config->get_seamless_loop ();
91
92         if (dynamic_cast<JACK_Slave*>(new_slave)) {
93                 /* JACK cannot support seamless looping at present */
94                 Config->set_seamless_loop (false);
95         } else {
96                 /* reset to whatever the value was before we last switched slaves */
97                 Config->set_seamless_loop (_was_seamless);
98         }
99
100         /* save value of seamless from before the switch */
101         _was_seamless = seamless;
102
103         ev->slave = new_slave;
104         queue_event (ev);
105 }
106
107 void
108 Session::request_transport_speed (double speed)
109 {
110         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
111         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1\n", speed));
112         queue_event (ev);
113 }
114
115 /** Request a new transport speed, but if the speed parameter is exactly zero then use
116  *  a very small +ve value to prevent the transport actually stopping.  This method should
117  *  be used by callers who are varying transport speed but don't ever want to stop it.
118  */
119 void
120 Session::request_transport_speed_nonzero (double speed)
121 {
122         if (speed == 0) {
123                 speed = DBL_EPSILON;
124         }
125
126         request_transport_speed (speed);
127 }
128
129 void
130 Session::request_track_speed (Track* tr, double speed)
131 {
132         SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
133         ev->set_ptr (tr);
134         queue_event (ev);
135 }
136
137 void
138 Session::request_stop (bool abort, bool clear_state)
139 {
140         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0, abort, clear_state);
141         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, abort = %1, clear state = %2\n", abort, clear_state));
142         queue_event (ev);
143 }
144
145 void
146 Session::request_locate (framepos_t target_frame, bool with_roll)
147 {
148         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
149         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
150         queue_event (ev);
151 }
152
153 void
154 Session::force_locate (framepos_t target_frame, bool with_roll)
155 {
156         SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
157         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
158         queue_event (ev);
159 }
160
161 void
162 Session::request_play_loop (bool yn, bool leave_rolling)
163 {
164         SessionEvent* ev;
165         Location *location = _locations->auto_loop_location();
166
167         if (location == 0 && yn) {
168                 error << _("Cannot loop - no loop range defined")
169                       << endmsg;
170                 return;
171         }
172
173         ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn);
174         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, leave rolling ? %2\n", yn, leave_rolling));
175         queue_event (ev);
176
177         if (!leave_rolling && !yn && Config->get_seamless_loop() && transport_rolling()) {
178                 // request an immediate locate to refresh the tracks
179                 // after disabling looping
180                 request_locate (_transport_frame-1, false);
181         }
182 }
183
184 void
185 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
186 {
187         SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
188         if (range) {
189                 ev->audio_range = *range;
190         } else {
191                 ev->audio_range.clear ();
192         }
193         DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
194         queue_event (ev);
195 }
196
197 void
198 Session::realtime_stop (bool abort, bool clear_state)
199 {
200         DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
201         PostTransportWork todo = PostTransportWork (0);
202
203         /* assume that when we start, we'll be moving forwards */
204
205         if (_transport_speed < 0.0f) {
206                 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
207         } else {
208                 todo = PostTransportWork (todo | PostTransportStop);
209         }
210
211         /* call routes */
212
213         boost::shared_ptr<RouteList> r = routes.reader ();
214
215         for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
216                 (*i)->realtime_handle_transport_stopped ();
217         }
218
219         if (actively_recording()) {
220
221                 /* move the transport position back to where the
222                    request for a stop was noticed. we rolled
223                    past that point to pick up delayed input (and/or to delick)
224                 */
225
226                 if (worst_playback_latency() > current_block_size) {
227                         /* we rolled past the stop point to pick up data that had
228                            not yet arrived. move back to where the stop occured.
229                         */
230                         decrement_transport_position (current_block_size + (worst_input_latency() - current_block_size));
231                 } else {
232                         decrement_transport_position (current_block_size);
233                 }
234
235                 /* the duration change is not guaranteed to have happened, but is likely */
236
237                 todo = PostTransportWork (todo | PostTransportDuration);
238         }
239
240         if (abort) {
241                 todo = PostTransportWork (todo | PostTransportAbort);
242         }
243
244         if (clear_state) {
245                 todo = PostTransportWork (todo | PostTransportClearSubstate);
246         }
247
248         if (todo) {
249                 add_post_transport_work (todo);
250         }
251
252         _clear_event_type (SessionEvent::StopOnce);
253         _clear_event_type (SessionEvent::RangeStop);
254         _clear_event_type (SessionEvent::RangeLocate);
255
256         /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
257         disable_record (true, (!Config->get_latched_record_enable() && clear_state));
258
259         reset_slave_state ();
260
261         _transport_speed = 0;
262         _target_transport_speed = 0;
263
264         g_atomic_int_set (&_playback_load, 100);
265         g_atomic_int_set (&_capture_load, 100);
266
267         if (config.get_use_video_sync()) {
268                 waiting_for_sync_offset = true;
269         }
270
271         transport_sub_state = 0;
272 }
273
274 void
275 Session::realtime_locate ()
276 {
277         boost::shared_ptr<RouteList> r = routes.reader ();
278         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
279                 (*i)->realtime_locate ();
280         }
281 }
282
283 void
284 Session::butler_transport_work ()
285 {
286   restart:
287         bool finished;
288         PostTransportWork ptw;
289         boost::shared_ptr<RouteList> r = routes.reader ();
290
291         int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
292         finished = true;
293         ptw = post_transport_work();
294
295         DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1\n", enum_2_string (ptw)));
296
297         if (ptw & PostTransportAdjustPlaybackBuffering) {
298                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
299                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
300                         if (tr) {
301                                 tr->adjust_playback_buffering ();
302                                 /* and refill those buffers ... */
303                                 tr->non_realtime_locate (_transport_frame);
304                         }
305                 }
306
307         }
308
309         if (ptw & PostTransportAdjustCaptureBuffering) {
310                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
311                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
312                         if (tr) {
313                                 tr->adjust_capture_buffering ();
314                         }
315                 }
316         }
317
318         if (ptw & PostTransportCurveRealloc) {
319                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
320                         (*i)->curve_reallocate();
321                 }
322         }
323
324         if (ptw & PostTransportInputChange) {
325                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
326                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
327                         if (tr) {
328                                 tr->non_realtime_input_change ();
329                         }
330                 }
331         }
332
333         if (ptw & PostTransportSpeed) {
334                 non_realtime_set_speed ();
335         }
336
337         if (ptw & PostTransportReverse) {
338
339                 clear_clicks();
340                 cumulative_rf_motion = 0;
341                 reset_rf_scale (0);
342
343                 /* don't seek if locate will take care of that in non_realtime_stop() */
344
345                 if (!(ptw & PostTransportLocate)) {
346
347                         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
348                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
349                                 if (tr && !tr->hidden()) {
350                                         tr->non_realtime_locate (_transport_frame);
351                                 }
352                                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
353                                         /* new request, stop seeking, and start again */
354                                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
355                                         goto restart;
356                                 }
357                         }
358                 }
359         }
360
361         if (ptw & PostTransportLocate) {
362                 non_realtime_locate ();
363         }
364
365         if (ptw & PostTransportStop) {
366                 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
367                 if (!finished) {
368                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
369                         goto restart;
370                 }
371         }
372
373         if (ptw & PostTransportOverWrite) {
374                 non_realtime_overwrite (on_entry, finished);
375                 if (!finished) {
376                         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
377                         goto restart;
378                 }
379         }
380
381         if (ptw & PostTransportAudition) {
382                 non_realtime_set_audition ();
383         }
384
385         g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
386
387         DEBUG_TRACE (DEBUG::Transport, X_("Butler transport work all done\n"));
388 }
389
390 void
391 Session::non_realtime_set_speed ()
392 {
393         boost::shared_ptr<RouteList> rl = routes.reader();
394         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
395                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
396                 if (tr) {
397                         tr->non_realtime_set_speed ();
398                 }
399         }
400 }
401
402 void
403 Session::non_realtime_overwrite (int on_entry, bool& finished)
404 {
405         boost::shared_ptr<RouteList> rl = routes.reader();
406         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
407                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
408                 if (tr && tr->pending_overwrite ()) {
409                         tr->overwrite_existing_buffers ();
410                 }
411                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
412                         finished = false;
413                         return;
414                 }
415         }
416 }
417
418
419 void
420 Session::non_realtime_locate ()
421 {
422         boost::shared_ptr<RouteList> rl = routes.reader();
423         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
424                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
425                 if (tr) {
426                         tr->non_realtime_locate (_transport_frame);
427                 }
428         }
429
430         /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
431            rather than clearing them so that the RT thread has to spend time constructing
432            them (in Session::click).
433          */
434         clear_clicks ();
435 }
436
437
438 void
439 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
440 {
441         struct tm* now;
442         time_t     xnow;
443         bool       did_record;
444         bool       saved;
445         PostTransportWork ptw = post_transport_work();
446
447         did_record = false;
448         saved = false;
449
450         boost::shared_ptr<RouteList> rl = routes.reader();
451         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
452                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
453                 if (tr && tr->get_captured_frames () != 0) {
454                         did_record = true;
455                         break;
456                 }
457         }
458
459         /* stop and locate are merged here because they share a lot of common stuff */
460
461         time (&xnow);
462         now = localtime (&xnow);
463
464         if (auditioner) {
465                 auditioner->cancel_audition ();
466         }
467
468         cumulative_rf_motion = 0;
469         reset_rf_scale (0);
470
471         if (did_record) {
472                 begin_reversible_command (Operations::capture);
473                 _have_captured = true;
474         }
475
476         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
477
478         if (abort && did_record) {
479                 /* no reason to save the session file when we remove sources
480                  */
481                 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
482         }
483
484         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
485                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
486                 if (tr) {
487                         tr->transport_stopped_wallclock (*now, xnow, abort);
488                 }
489         }
490
491         if (abort && did_record) {
492                 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
493         }
494
495         boost::shared_ptr<RouteList> r = routes.reader ();
496
497         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
498                 if (!(*i)->is_hidden()) {
499                         (*i)->set_pending_declick (0);
500                 }
501         }
502
503         if (did_record) {
504                 commit_reversible_command ();
505         }
506
507         if (_engine.running()) {
508                 PostTransportWork ptw = post_transport_work ();
509                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
510                         (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
511                 }
512                 update_latency_compensation ();
513         }
514
515         bool const auto_return_enabled =
516                 (!config.get_external_sync() && config.get_auto_return());
517
518         if (auto_return_enabled ||
519             (ptw & PostTransportLocate) ||
520             (_requested_return_frame >= 0) ||
521             synced_to_jack()) {
522
523                 if (pending_locate_flush) {
524                         flush_all_inserts ();
525                 }
526
527                 if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
528                     !(ptw & PostTransportLocate)) {
529
530                         /* no explicit locate queued */
531
532                         bool do_locate = false;
533
534                         if (_requested_return_frame >= 0) {
535
536                                 /* explicit return request pre-queued in event list. overrides everything else */
537
538                                 cerr << "explicit auto-return to " << _requested_return_frame << endl;
539
540                                 _transport_frame = _requested_return_frame;
541                                 do_locate = true;
542
543                         } else {
544                                 if (config.get_auto_return()) {
545
546                                         if (play_loop) {
547
548                                                 /* don't try to handle loop play when synced to JACK */
549
550                                                 if (!synced_to_jack()) {
551
552                                                         Location *location = _locations->auto_loop_location();
553
554                                                         if (location != 0) {
555                                                                 _transport_frame = location->start();
556                                                         } else {
557                                                                 _transport_frame = _last_roll_location;
558                                                         }
559                                                         do_locate = true;
560                                                 }
561
562                                         } else if (_play_range) {
563
564                                                 /* return to start of range */
565
566                                                 if (!current_audio_range.empty()) {
567                                                         _transport_frame = current_audio_range.front().start;
568                                                         do_locate = true;
569                                                 }
570
571                                         } else {
572
573                                                 /* regular auto-return */
574
575                                                 _transport_frame = _last_roll_location;
576                                                 do_locate = true;
577                                         }
578                                 }
579                         }
580
581                         _requested_return_frame = -1;
582
583                         if (do_locate) {
584                                 _engine.transport_locate (_transport_frame);
585                         }
586                 }
587
588         }
589
590         clear_clicks();
591
592         /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
593         */
594
595         if (ptw & PostTransportClearSubstate) {
596                 _play_range = false;
597                 unset_play_loop ();
598         }
599
600         /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
601
602         DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
603         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
604                 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
605                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
606                 if (tr && !tr->hidden()) {
607                         tr->non_realtime_locate (_transport_frame);
608                 }
609
610                 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
611                         finished = false;
612                         /* we will be back */
613                         return;
614                 }
615         }
616
617         have_looped = false;
618
619         if (!_engine.freewheeling()) {
620                 send_full_time_code (_transport_frame);
621                 
622                 if (!dynamic_cast<MTC_Slave*>(_slave)) {
623                         MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
624                         send_mmc_locate (_transport_frame);
625                 }
626         }
627
628         if ((ptw & PostTransportLocate) && get_record_enabled()) {
629                 /* capture start has been changed, so save pending state */
630                 save_state ("", true);
631                 saved = true;
632         }
633
634         /* always try to get rid of this */
635
636         remove_pending_capture_state ();
637
638         /* save the current state of things if appropriate */
639
640         if (did_record && !saved) {
641                 save_state (_current_snapshot_name);
642         }
643
644         if (ptw & PostTransportStop) {
645                 _play_range = false;
646                 play_loop = false;
647         }
648
649         PositionChanged (_transport_frame); /* EMIT SIGNAL */
650         TransportStateChange (); /* EMIT SIGNAL */
651
652         /* and start it up again if relevant */
653
654         if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
655                 request_transport_speed (1.0);
656                 pending_locate_roll = false;
657         }
658 }
659
660 void
661 Session::check_declick_out ()
662 {
663         bool locate_required = transport_sub_state & PendingLocate;
664
665         /* this is called after a process() iteration. if PendingDeclickOut was set,
666            it means that we were waiting to declick the output (which has just been
667            done) before doing something else. this is where we do that "something else".
668
669            note: called from the audio thread.
670         */
671
672         if (transport_sub_state & PendingDeclickOut) {
673
674                 if (locate_required) {
675                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
676                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
677                 } else {
678                         stop_transport (pending_abort);
679                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
680                 }
681         }
682 }
683
684 void
685 Session::unset_play_loop ()
686 {
687         play_loop = false;
688         clear_events (SessionEvent::AutoLoop);
689
690         // set all tracks to NOT use internal looping
691         boost::shared_ptr<RouteList> rl = routes.reader ();
692         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
693                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
694                 if (tr && !tr->hidden()) {
695                         tr->set_loop (0);
696                 }
697         }
698 }
699
700 void
701 Session::set_play_loop (bool yn)
702 {
703         /* Called from event-handling context */
704
705         Location *loc;
706
707         if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
708                 /* nothing to do, or can't change loop status while recording */
709                 return;
710         }
711
712         if (yn && Config->get_seamless_loop() && synced_to_jack()) {
713                 warning << string_compose (
714                         _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
715                           "Recommend changing the configured options"), PROGRAM_NAME)
716                         << endmsg;
717                 return;
718         }
719
720         if (yn) {
721
722                 play_loop = true;
723
724                 if (loc) {
725
726                         unset_play_range ();
727
728                         if (Config->get_seamless_loop()) {
729                                 // set all tracks to use internal looping
730                                 boost::shared_ptr<RouteList> rl = routes.reader ();
731                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
732                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
733                                         if (tr && !tr->hidden()) {
734                                                 tr->set_loop (loc);
735                                         }
736                                 }
737                         }
738                         else {
739                                 // set all tracks to NOT use internal looping
740                                 boost::shared_ptr<RouteList> rl = routes.reader ();
741                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
742                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
743                                         if (tr && !tr->hidden()) {
744                                                 tr->set_loop (0);
745                                         }
746                                 }
747                         }
748
749                         /* put the loop event into the event list */
750
751                         SessionEvent* event = new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f);
752                         merge_event (event);
753
754                         /* locate to start of loop and roll. If doing seamless loop, force a
755                            locate+buffer refill even if we are positioned there already.
756                         */
757
758                         start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
759                 }
760
761         } else {
762
763                 unset_play_loop ();
764         }
765
766         TransportStateChange ();
767 }
768 void
769 Session::flush_all_inserts ()
770 {
771         boost::shared_ptr<RouteList> r = routes.reader ();
772
773         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
774                 (*i)->flush_processors ();
775         }
776 }
777
778 void
779 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
780 {
781         if (synced_to_jack()) {
782
783                 double sp;
784                 framepos_t pos;
785
786                 _slave->speed_and_position (sp, pos);
787
788                 if (target_frame != pos) {
789
790                         /* tell JACK to change transport position, and we will
791                            follow along later in ::follow_slave()
792                         */
793
794                         _engine.transport_locate (target_frame);
795
796                         if (sp != 1.0f && with_roll) {
797                                 _engine.transport_start ();
798                         }
799
800                 }
801
802         } else {
803                 locate (target_frame, with_roll, with_flush, with_loop, force);
804         }
805 }
806
807 int
808 Session::micro_locate (framecnt_t distance)
809 {
810         boost::shared_ptr<RouteList> rl = routes.reader();
811         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
812                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
813                 if (tr && !tr->can_internal_playback_seek (distance)) {
814                         return -1;
815                 }
816         }
817
818         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
819                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
820                 if (tr) {
821                         tr->internal_playback_seek (distance);
822                 }
823         }
824
825         _transport_frame += distance;
826         return 0;
827 }
828
829 /** @param with_mmc true to send a MMC locate command when the locate is done */
830 void
831 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force, bool with_mmc)
832 {
833         if (actively_recording() && !with_loop) {
834                 return;
835         }
836
837         if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
838                 if (with_roll) {
839                         set_transport_speed (1.0, false);
840                 }
841                 loop_changing = false;
842                 Located (); /* EMIT SIGNAL */
843                 return;
844         }
845
846         if (_transport_speed) {
847                 /* schedule a declick. we'll be called again when its done */
848
849                 if (!(transport_sub_state & PendingDeclickOut)) {
850                         transport_sub_state |= (PendingDeclickOut|PendingLocate);
851                         pending_locate_frame = target_frame;
852                         pending_locate_roll = with_roll;
853                         pending_locate_flush = with_flush;
854                         return;
855                 }
856         }
857
858         // Update Timecode time
859         // [DR] FIXME: find out exactly where this should go below
860         _transport_frame = target_frame;
861         timecode_time(_transport_frame, transmitting_timecode_time);
862         outbound_mtc_timecode_frame = _transport_frame;
863         next_quarter_frame_to_send = 0;
864
865         /* do "stopped" stuff if:
866          *
867          * we are rolling AND
868          *    no autoplay in effect AND
869          *       we're not going to keep rolling after the locate AND
870          *           !(playing a loop with JACK sync)
871          *
872          */
873
874         if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
875                 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
876         } else {
877                 /* otherwise tell the world that we located */
878                 realtime_locate ();
879         }
880
881         if (force || !with_loop || loop_changing) {
882
883                 PostTransportWork todo = PostTransportLocate;
884
885                 if (with_roll) {
886                         todo = PostTransportWork (todo | PostTransportRoll);
887                 }
888
889                 add_post_transport_work (todo);
890                 _butler->schedule_transport_work ();
891
892         } else {
893
894                 /* this is functionally what clear_clicks() does but with a tentative lock */
895
896                 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
897
898                 if (clickm.locked()) {
899
900                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
901                                 delete *i;
902                         }
903
904                         clicks.clear ();
905                 }
906         }
907
908         if (with_roll) {
909                 /* switch from input if we're going to roll */
910                 if (Config->get_monitoring_model() == HardwareMonitoring) {
911                         set_track_monitor_input_status (!config.get_auto_input());
912                 }
913         } else {
914                 /* otherwise we're going to stop, so do the opposite */
915                 if (Config->get_monitoring_model() == HardwareMonitoring) {
916                         set_track_monitor_input_status (true);
917                 }
918         }
919
920         /* cancel looped playback if transport pos outside of loop range */
921         if (play_loop) {
922                 Location* al = _locations->auto_loop_location();
923
924                 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
925                         // cancel looping directly, this is called from event handling context
926                         set_play_loop (false);
927                 }
928                 else if (al && _transport_frame == al->start()) {
929                         if (with_loop) {
930                                 // this is only necessary for seamless looping
931
932                                 boost::shared_ptr<RouteList> rl = routes.reader();
933                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
934                                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
935                                         if (tr && tr->record_enabled ()) {
936                                                 // tell it we've looped, so it can deal with the record state
937                                                 tr->transport_looped(_transport_frame);
938                                         }
939                                 }
940                         }
941                         have_looped = true;
942                         TransportLooped(); // EMIT SIGNAL
943                 }
944         }
945
946         loop_changing = false;
947
948         _send_timecode_update = true;
949
950         if (with_mmc) {
951                 send_mmc_locate (_transport_frame);
952         }
953
954         Located (); /* EMIT SIGNAL */
955 }
956
957 /** Set the transport speed.
958  *  Called from the process thread.
959  *  @param speed New speed
960  */
961 void
962 Session::set_transport_speed (double speed, bool abort, bool clear_state)
963 {
964         DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4\n", 
965                                                        speed, abort, clear_state, _transport_speed, _transport_frame));
966
967         if (_transport_speed == speed) {
968                 return;
969         }
970
971         if (actively_recording() && speed != 1.0 && speed != 0.0) {
972                 /* no varispeed during recording */
973                 return;
974         }
975
976         _target_transport_speed = fabs(speed);
977
978         /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
979            and user needs. We really need CD-style "skip" playback for ffwd and rewind.
980         */
981
982         if (speed > 0) {
983                 speed = min (8.0, speed);
984         } else if (speed < 0) {
985                 speed = max (-8.0, speed);
986         }
987
988         if (transport_rolling() && speed == 0.0) {
989
990                 /* we are rolling and we want to stop */
991
992                 if (Config->get_monitoring_model() == HardwareMonitoring) {
993                         set_track_monitor_input_status (true);
994                 }
995
996                 if (synced_to_jack ()) {
997                         if (clear_state) {
998                                 /* do this here because our response to the slave won't
999                                    take care of it.
1000                                 */
1001                                 _play_range = false;
1002                                 unset_play_loop ();
1003                         }
1004                         _engine.transport_stop ();
1005                 } else {
1006                         stop_transport (abort);
1007                 }
1008
1009                 unset_play_loop ();
1010
1011         } else if (transport_stopped() && speed == 1.0) {
1012
1013                 /* we are stopped and we want to start rolling at speed 1 */
1014
1015                 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1016                         set_track_monitor_input_status (false);
1017                 }
1018
1019                 if (synced_to_jack()) {
1020                         _engine.transport_start ();
1021                 } else {
1022                         start_transport ();
1023                 }
1024
1025         } else {
1026
1027                 /* not zero, not 1.0 ... varispeed */
1028
1029                 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
1030                         warning << string_compose (
1031                                 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1032                                 PROGRAM_NAME)
1033                                 << endmsg;
1034                         return;
1035                 }
1036
1037                 if (actively_recording()) {
1038                         return;
1039                 }
1040
1041                 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1042                         return;
1043                 }
1044
1045                 if (speed < 0.0 && _transport_frame == 0) {
1046                         return;
1047                 }
1048
1049                 clear_clicks ();
1050
1051                 /* if we are reversing relative to the current speed, or relative to the speed
1052                    before the last stop, then we have to do extra work.
1053                 */
1054
1055                 PostTransportWork todo = PostTransportWork (0);
1056
1057                 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
1058                         todo = PostTransportWork (todo | PostTransportReverse);
1059                         _last_roll_or_reversal_location = _transport_frame;
1060                 }
1061
1062                 _last_transport_speed = _transport_speed;
1063                 _transport_speed = speed;
1064
1065                 boost::shared_ptr<RouteList> rl = routes.reader();
1066                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1067                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1068                         if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1069                                 todo = PostTransportWork (todo | PostTransportSpeed);
1070                         }
1071                 }
1072
1073                 if (todo) {
1074                         add_post_transport_work (todo);
1075                         _butler->schedule_transport_work ();
1076                 }
1077
1078                 TransportStateChange (); /* EMIT SIGNAL */
1079         }
1080 }
1081
1082
1083 /** Stop the transport.  */
1084 void
1085 Session::stop_transport (bool abort, bool clear_state)
1086 {
1087         if (_transport_speed == 0.0f) {
1088                 return;
1089         }
1090
1091         if (actively_recording() && !(transport_sub_state & StopPendingCapture) && worst_input_latency() > current_block_size) {
1092
1093                 boost::shared_ptr<RouteList> rl = routes.reader();
1094                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1095                         boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1096                         if (tr) {
1097                                 tr->prepare_to_stop (_transport_frame);
1098                         }
1099                 }
1100
1101                 /* we need to capture the audio that has still not yet been received by the system
1102                    at the time the stop is requested, so we have to roll past that time.
1103
1104                    we want to declick before stopping, so schedule the autostop for one
1105                    block before the actual end. we'll declick in the subsequent block,
1106                    and then we'll really be stopped.
1107                 */
1108
1109                 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 - %3 = %4, abort = %5\n",
1110                                                                _transport_frame, _worst_input_latency, current_block_size,
1111                                                                _transport_frame - _worst_input_latency - current_block_size,
1112                                                                abort));
1113
1114                 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1115                                                      _transport_frame + _worst_input_latency - current_block_size,
1116                                                      0, 0, abort);
1117
1118                 merge_event (ev);
1119                 transport_sub_state |= StopPendingCapture;
1120                 pending_abort = abort;
1121                 return;
1122         }
1123
1124         if ((transport_sub_state & PendingDeclickOut) == 0) {
1125
1126                 if (!(transport_sub_state & StopPendingCapture)) {
1127                         boost::shared_ptr<RouteList> rl = routes.reader();
1128                         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1129                                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1130                                 if (tr) {
1131                                         tr->prepare_to_stop (_transport_frame);
1132                                 }
1133                         }
1134                 }
1135
1136                 transport_sub_state |= PendingDeclickOut;
1137                 /* we'll be called again after the declick */
1138                 pending_abort = abort;
1139                 return;
1140         }
1141
1142         realtime_stop (abort, clear_state);
1143         _butler->schedule_transport_work ();
1144 }
1145
1146 /** Called from the process thread */
1147 void
1148 Session::start_transport ()
1149 {
1150         DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1151
1152         _last_roll_location = _transport_frame;
1153         _last_roll_or_reversal_location = _transport_frame;
1154
1155         have_looped = false;
1156
1157         /* if record status is Enabled, move it to Recording. if its
1158            already Recording, move it to Disabled.
1159         */
1160
1161         switch (record_status()) {
1162         case Enabled:
1163                 if (!config.get_punch_in()) {
1164                         enable_record ();
1165                 }
1166                 break;
1167
1168         case Recording:
1169                 if (!play_loop) {
1170                         disable_record (false);
1171                 }
1172                 break;
1173
1174         default:
1175                 break;
1176         }
1177
1178         transport_sub_state |= PendingDeclickIn;
1179
1180         _transport_speed = 1.0;
1181         _target_transport_speed = 1.0;
1182
1183         boost::shared_ptr<RouteList> rl = routes.reader();
1184         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1185                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1186                 if (tr) {
1187                         tr->realtime_set_speed (tr->speed(), true);
1188                 }
1189                 (*i)->automation_snapshot (_transport_frame, true);
1190         }
1191
1192         if (!_engine.freewheeling()) {
1193                 Timecode::Time time;
1194                 timecode_time_subframes (_transport_frame, time);
1195                 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1196                         MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1197                 }
1198         }
1199
1200         TransportStateChange (); /* EMIT SIGNAL */
1201 }
1202
1203 /** Do any transport work in the audio thread that needs to be done after the
1204  * transport thread is finished.  Audio thread, realtime safe.
1205  */
1206 void
1207 Session::post_transport ()
1208 {
1209         PostTransportWork ptw = post_transport_work ();
1210
1211         if (ptw & PostTransportAudition) {
1212                 if (auditioner && auditioner->auditioning()) {
1213                         process_function = &Session::process_audition;
1214                 } else {
1215                         process_function = &Session::process_with_events;
1216                 }
1217         }
1218
1219         if (ptw & PostTransportStop) {
1220
1221                 transport_sub_state = 0;
1222         }
1223
1224         if (ptw & PostTransportLocate) {
1225
1226                 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1227                         start_transport ();
1228
1229                 } else {
1230                         transport_sub_state = 0;
1231                 }
1232         }
1233
1234         set_next_event ();
1235         /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1236            know were handled ?
1237         */
1238         set_post_transport_work (PostTransportWork (0));
1239 }
1240
1241 void
1242 Session::reset_rf_scale (framecnt_t motion)
1243 {
1244         cumulative_rf_motion += motion;
1245
1246         if (cumulative_rf_motion < 4 * _current_frame_rate) {
1247                 rf_scale = 1;
1248         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1249                 rf_scale = 4;
1250         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1251                 rf_scale = 10;
1252         } else {
1253                 rf_scale = 100;
1254         }
1255
1256         if (motion != 0) {
1257                 set_dirty();
1258         }
1259 }
1260
1261 void
1262 Session::use_sync_source (Slave* new_slave)
1263 {
1264         /* Runs in process() context */
1265
1266         bool non_rt_required = false;
1267
1268         /* XXX this deletion is problematic because we're in RT context */
1269
1270         delete _slave;
1271         _slave = new_slave;
1272
1273         send_full_time_code (_transport_frame);
1274
1275         boost::shared_ptr<RouteList> rl = routes.reader();
1276         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1277                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1278                 if (tr && !tr->hidden()) {
1279                         if (tr->realtime_set_speed (tr->speed(), true)) {
1280                                 non_rt_required = true;
1281                         }
1282                         tr->set_slaved (_slave != 0);
1283                 }
1284         }
1285
1286         if (non_rt_required) {
1287                 add_post_transport_work (PostTransportSpeed);
1288                 _butler->schedule_transport_work ();
1289         }
1290
1291         set_dirty();
1292 }
1293
1294 void
1295 Session::drop_sync_source ()
1296 {
1297         request_sync_source (0);
1298 }
1299
1300 void
1301 Session::switch_to_sync_source (SyncSource src)
1302 {
1303         Slave* new_slave;
1304
1305         DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1306
1307         switch (src) {
1308         case MTC:
1309                 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1310                         return;
1311                 }
1312
1313                 try {
1314                         new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
1315                 }
1316
1317                 catch (failed_constructor& err) {
1318                         return;
1319                 }
1320                 break;
1321
1322         case MIDIClock:
1323                 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1324                         return;
1325                 }
1326
1327                 try {
1328                         new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
1329                 }
1330
1331                 catch (failed_constructor& err) {
1332                         return;
1333                 }
1334                 break;
1335
1336         case JACK:
1337                 if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
1338                         return;
1339                 }
1340
1341                 if (config.get_video_pullup() != 0.0f) {
1342                         return;
1343                 }
1344
1345                 new_slave = new JACK_Slave (_engine.jack());
1346                 break;
1347
1348         default:
1349                 new_slave = 0;
1350                 break;
1351         };
1352
1353         request_sync_source (new_slave);
1354 }
1355
1356 void
1357 Session::set_track_speed (Track* track, double speed)
1358 {
1359         if (track->realtime_set_speed (speed, false)) {
1360                 add_post_transport_work (PostTransportSpeed);
1361                 _butler->schedule_transport_work ();
1362                 set_dirty ();
1363         }
1364 }
1365
1366 void
1367 Session::unset_play_range ()
1368 {
1369         _play_range = false;
1370         _clear_event_type (SessionEvent::RangeStop);
1371         _clear_event_type (SessionEvent::RangeLocate);
1372 }
1373
1374 void
1375 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1376 {
1377         SessionEvent* ev;
1378
1379         /* Called from event-processing context */
1380
1381         unset_play_range ();
1382
1383         if (range.empty()) {
1384                 /* _play_range set to false in unset_play_range()
1385                  */
1386                 if (!leave_rolling) {
1387                         /* stop transport */
1388                         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1389                         merge_event (ev);
1390                 }
1391                 return;
1392         }
1393
1394         _play_range = true;
1395
1396         /* cancel loop play */
1397         unset_play_loop ();
1398
1399         list<AudioRange>::size_type sz = range.size();
1400
1401         if (sz > 1) {
1402
1403                 list<AudioRange>::iterator i = range.begin();
1404                 list<AudioRange>::iterator next;
1405
1406                 while (i != range.end()) {
1407
1408                         next = i;
1409                         ++next;
1410
1411                         /* locating/stopping is subject to delays for declicking.
1412                          */
1413
1414                         framepos_t requested_frame = i->end;
1415
1416                         if (requested_frame > current_block_size) {
1417                                 requested_frame -= current_block_size;
1418                         } else {
1419                                 requested_frame = 0;
1420                         }
1421
1422                         if (next == range.end()) {
1423                                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1424                         } else {
1425                                 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1426                         }
1427
1428                         merge_event (ev);
1429
1430                         i = next;
1431                 }
1432
1433         } else if (sz == 1) {
1434
1435                 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1436                 merge_event (ev);
1437
1438         }
1439
1440         /* save range so we can do auto-return etc. */
1441
1442         current_audio_range = range;
1443
1444         /* now start rolling at the right place */
1445
1446         ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1447         merge_event (ev);
1448
1449         TransportStateChange ();
1450 }
1451
1452 void
1453 Session::request_bounded_roll (framepos_t start, framepos_t end)
1454 {
1455         AudioRange ar (start, end, 0);
1456         list<AudioRange> lar;
1457
1458         lar.push_back (ar);
1459         request_play_range (&lar, true);
1460 }
1461 void
1462 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1463 {
1464         SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1465         ev->target2_frame = start;
1466         queue_event (ev);
1467 }
1468
1469 void
1470 Session::engine_halted ()
1471 {
1472         bool ignored;
1473
1474         /* there will be no more calls to process(), so
1475            we'd better clean up for ourselves, right now.
1476
1477            but first, make sure the butler is out of
1478            the picture.
1479         */
1480
1481         g_atomic_int_set (&_butler->should_do_transport_work, 0);
1482         set_post_transport_work (PostTransportWork (0));
1483         _butler->stop ();
1484
1485         realtime_stop (false, true);
1486         non_realtime_stop (false, 0, ignored);
1487         transport_sub_state = 0;
1488
1489         TransportStateChange (); /* EMIT SIGNAL */
1490 }
1491
1492
1493 void
1494 Session::xrun_recovery ()
1495 {
1496         Xrun (_transport_frame); /* EMIT SIGNAL */
1497
1498         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1499
1500                 /* it didn't actually halt, but we need
1501                    to handle things in the same way.
1502                 */
1503
1504                 engine_halted();
1505         }
1506 }
1507
1508 void
1509 Session::route_processors_changed (RouteProcessorChange c)
1510 {
1511         if (ignore_route_processor_changes) {
1512                 return;
1513         }
1514
1515         if (c.type == RouteProcessorChange::MeterPointChange) {
1516                 return;
1517         }
1518
1519         update_latency_compensation ();
1520         resort_routes ();
1521
1522         set_dirty ();
1523 }
1524
1525 void
1526 Session::allow_auto_play (bool yn)
1527 {
1528         auto_play_legal = yn;
1529 }
1530
1531 void
1532 Session::reset_jack_connection (jack_client_t* jack)
1533 {
1534         JACK_Slave* js;
1535
1536         if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
1537                 js->reset_client (jack);
1538         }
1539 }
1540
1541 bool
1542 Session::maybe_stop (framepos_t limit)
1543 {
1544         if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1545                 if (synced_to_jack () && config.get_jack_time_master ()) {
1546                         _engine.transport_stop ();
1547                 } else if (!synced_to_jack ()) {
1548                         stop_transport ();
1549                 }
1550                 return true;
1551         }
1552         return false;
1553 }
1554
1555 void
1556 Session::send_mmc_locate (framepos_t t)
1557 {
1558         if (!_engine.freewheeling()) {
1559                 Timecode::Time time;
1560                 timecode_time_subframes (t, time);
1561                 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
1562         }
1563 }
1564
1565 /** Ask the transport to not send timecode until further notice.  The suspension
1566  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
1567  *  should be checked by the caller to find out when.
1568  */
1569 void
1570 Session::request_suspend_timecode_transmission ()
1571 {
1572         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1573         queue_event (ev);
1574 }
1575
1576 void
1577 Session::request_resume_timecode_transmission ()
1578 {
1579         SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1580         queue_event (ev);
1581 }
1582
1583 bool
1584 Session::timecode_transmission_suspended () const
1585 {
1586         return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
1587 }