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