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