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