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