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