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