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