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