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