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