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