Renamed id to _id for ObjC compatibility.
[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         }
415
416         /* always try to get rid of this */
417
418         remove_pending_capture_state ();
419         
420         /* save the current state of things if appropriate */
421
422         if (did_record) {
423                 save_state (_current_snapshot_name);
424         }
425
426         if (post_transport_work & PostTransportDuration) {
427                 DurationChanged (); /* EMIT SIGNAL */
428         }
429
430         if (post_transport_work & PostTransportStop) { 
431                 _play_range = false;
432
433                 /* do not turn off autoloop on stop */
434
435         }
436
437         PositionChanged (_transport_frame); /* EMIT SIGNAL */
438         TransportStateChange (); /* EMIT SIGNAL */
439
440         /* and start it up again if relevant */
441
442         if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
443                 request_transport_speed (1.0);
444                 pending_locate_roll = false;
445         }
446 }
447
448 void
449 Session::check_declick_out ()
450 {
451         bool locate_required = transport_sub_state & PendingLocate;
452
453         /* this is called after a process() iteration. if PendingDeclickOut was set,
454            it means that we were waiting to declick the output (which has just been
455            done) before doing something else. this is where we do that "something else".
456            
457            note: called from the audio thread.
458         */
459
460         if (transport_sub_state & PendingDeclickOut) {
461
462                 if (locate_required) {
463                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
464                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
465                 } else {
466                         stop_transport (pending_abort);
467                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
468                 }
469         }
470 }
471
472 void
473 Session::set_auto_loop (bool yn)
474 {
475         /* Called from event-handling context */
476         
477         if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
478                 return;
479         }
480         
481         set_dirty();
482
483         if (yn && seamless_loop && synced_to_jack()) {
484                 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
485                              "Recommend changing the configured options")
486                         << endmsg;
487                 return;
488         }
489
490         
491         if ((auto_loop = yn)) {
492
493                 Location *loc;
494
495                 
496                 if ((loc = _locations.auto_loop_location()) != 0) {
497
498                         if (seamless_loop) {
499                                 // set all diskstreams to use internal looping
500                                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
501                                         if (!(*i)->hidden()) {
502                                                 (*i)->set_loop (loc);
503                                         }
504                                 }
505                         }
506                         else {
507                                 // set all diskstreams to NOT use internal looping
508                                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
509                                         if (!(*i)->hidden()) {
510                                                 (*i)->set_loop (0);
511                                         }
512                                 }
513                         }
514                         
515                         /* stick in the loop event */
516                         
517                         Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
518                         merge_event (event);
519
520                         /* locate to start of loop and roll if current pos is outside of the loop range */
521                         if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
522                                 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
523                                 merge_event (event);
524                         }
525                         else {
526                                 // locate to current position (+ 1 to force reload)
527                                 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
528                                 merge_event (event);
529                         }
530                 }
531
532
533
534         } else {
535                 clear_events (Event::AutoLoop);
536
537                 // set all diskstreams to NOT use internal looping
538                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
539                         if (!(*i)->hidden()) {
540                                 (*i)->set_loop (0);
541                         }
542                 }
543                 
544         }
545         
546         ControlChanged (AutoLoop); /* EMIT SIGNAL */
547 }
548
549 void
550 Session::flush_all_redirects ()
551 {
552         boost::shared_ptr<RouteList> r = routes.reader ();
553
554         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
555                 (*i)->flush_redirects ();
556         }
557 }
558
559 void
560 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
561 {
562         if (synced_to_jack()) {
563
564                 float sp;
565                 jack_nframes_t pos;
566
567                 _slave->speed_and_position (sp, pos);
568
569                 if (target_frame != pos) {
570
571                         /* tell JACK to change transport position, and we will
572                            follow along later in ::follow_slave()
573                         */
574
575                         _engine.transport_locate (target_frame);
576
577                         if (sp != 1.0f && with_roll) {
578                                 _engine.transport_start ();
579                         }
580
581                 }
582
583         } else {
584
585                 locate (target_frame, with_roll, with_flush, with_loop);
586         }
587 }
588
589 void
590 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
591 {
592         if (actively_recording()) {
593                 return;
594         }
595
596         if (_transport_frame == target_frame && !loop_changing && !with_loop) {
597                 if (with_roll) {
598                         set_transport_speed (1.0, false);
599                 }
600                 loop_changing = false;
601                 return;
602         }
603
604         _transport_frame = target_frame;
605
606         if (_transport_speed && (!with_loop || loop_changing)) {
607                 /* schedule a declick. we'll be called again when its done */
608
609                 if (!(transport_sub_state & PendingDeclickOut)) {
610                         transport_sub_state |= (PendingDeclickOut|PendingLocate);
611                         pending_locate_frame = target_frame;
612                         pending_locate_roll = with_roll;
613                         pending_locate_flush = with_flush;
614                         return;
615                 } 
616         }
617
618         if (transport_rolling() && !auto_play && !with_roll && !(synced_to_jack() && auto_loop)) {
619                 realtime_stop (false);
620         } 
621
622         if ( !with_loop || loop_changing) {
623
624                 post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
625                 
626                 if (with_roll) {
627                         post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
628                 }
629
630                 schedule_butler_transport_work ();
631
632         } else {
633
634                 /* this is functionally what clear_clicks() does but with a tentative lock */
635
636                 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
637         
638                 if (clickm.locked()) {
639                         
640                         for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
641                                 delete *i;
642                         }
643                 
644                         clicks.clear ();
645                 }
646         }
647
648         if (with_roll) {
649                 /* switch from input if we're going to roll */
650                 if (Config->get_use_hardware_monitoring()) {
651                         /* Even though this is called from RT context we are using
652                            a non-tentative rwlock here,  because the action must occur.
653                            The rarity and short potential lock duration makes this "OK"
654                         */
655                         Glib::RWLock::ReaderLock dsm (diskstream_lock);
656                         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
657                                 if ((*i)->record_enabled ()) {
658                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
659                                         (*i)->monitor_input (!auto_input);
660                                 }
661                         }
662                 }
663         } else {
664                 /* otherwise we're going to stop, so do the opposite */
665                 if (Config->get_use_hardware_monitoring()) {
666                         /* Even though this is called from RT context we are using
667                            a non-tentative rwlock here,  because the action must occur.
668                            The rarity and short potential lock duration makes this "OK"
669                         */
670                         Glib::RWLock::ReaderLock dsm (diskstream_lock);
671                         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
672                                 if ((*i)->record_enabled ()) {
673                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
674                                         (*i)->monitor_input (true);
675                                 }
676                         }
677                 }
678         }
679
680         /* cancel autoloop if transport pos outside of loop range */
681         if (auto_loop) {
682                 Location* al = _locations.auto_loop_location();
683                 
684                 if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
685                         // cancel looping directly, this is called from event handling context
686                         set_auto_loop(false);
687                 }
688         }
689         
690         loop_changing = false;
691 }
692
693 void
694 Session::set_transport_speed (float speed, bool abort)
695 {
696         if (_transport_speed == speed) {
697                 return;
698         }
699
700         if (speed > 0) {
701                 speed = min (8.0f, speed);
702         } else if (speed < 0) {
703                 speed = max (-8.0f, speed);
704         }
705
706         if (transport_rolling() && speed == 0.0) {
707
708                 if (Config->get_use_hardware_monitoring())
709                 {
710                         /* Even though this is called from RT context we are using
711                            a non-tentative rwlock here,  because the action must occur.
712                            The rarity and short potential lock duration makes this "OK"
713                         */
714                         Glib::RWLock::ReaderLock dsm (diskstream_lock);
715                         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
716                                 if ((*i)->record_enabled ()) {
717                                         //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
718                                         (*i)->monitor_input (true);     
719                                 }
720                         }
721                 }
722
723                 if (synced_to_jack ()) {
724                         _engine.transport_stop ();
725                 } else {
726                         stop_transport (abort);
727                 }
728
729         } else if (transport_stopped() && speed == 1.0) {
730
731                 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
732                         return;
733                 }
734
735                 if (Config->get_use_hardware_monitoring()) {
736                         /* Even though this is called from RT context we are using
737                            a non-tentative rwlock here,  because the action must occur.
738                            The rarity and short potential lock duration makes this "OK"
739                         */
740                         Glib::RWLock::ReaderLock dsm (diskstream_lock);
741                         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
742                                 if (auto_input && (*i)->record_enabled ()) {
743                                         //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
744                                         (*i)->monitor_input (false);    
745                                 }
746                         }
747                 }
748
749                 if (synced_to_jack()) {
750                         _engine.transport_start ();
751                 } else {
752                         start_transport ();
753                 }
754
755         } else {
756
757                 if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) {
758                         return;
759                 }
760
761                 if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) {
762                         warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control")
763                                 << endmsg;
764                         return;
765                 }
766
767                 if (actively_recording()) {
768                         return;
769                 }
770
771                 if (speed > 0.0f && _transport_frame == current_end_frame()) {
772                         return;
773                 }
774
775                 if (speed < 0.0f && _transport_frame == 0) {
776                         return;
777                 }
778                 
779                 clear_clicks ();
780
781                 /* if we are reversing relative to the current speed, or relative to the speed
782                    before the last stop, then we have to do extra work.
783                 */
784
785                 if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
786                         post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
787                 }
788                 
789                 _last_transport_speed = _transport_speed;
790                 _transport_speed = speed;
791                 
792                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
793                         if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
794                                 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
795                         }
796                 }
797                 
798                 if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
799                         schedule_butler_transport_work ();
800                 }
801         }
802 }
803
804 void
805 Session::stop_transport (bool abort)
806 {
807         if (_transport_speed == 0.0f) {
808                 return;
809         }
810
811         if (actively_recording() && !(transport_sub_state & StopPendingCapture) && 
812             _worst_output_latency > current_block_size) 
813         {
814                 
815                 /* we need to capture the audio that has still not yet been received by the system
816                    at the time the stop is requested, so we have to roll past that time.
817
818                    we want to declick before stopping, so schedule the autostop for one
819                    block before the actual end. we'll declick in the subsequent block,
820                    and then we'll really be stopped.
821                 */
822                 
823                 Event *ev = new Event (Event::StopOnce, Event::Replace, 
824                                        _transport_frame + _worst_output_latency - current_block_size,
825                                        0, 0, abort);
826                 
827                 merge_event (ev);
828                 transport_sub_state |= StopPendingCapture;
829                 pending_abort = abort;
830                 return;
831         } 
832
833         if ((transport_sub_state & PendingDeclickOut) == 0) {
834                 transport_sub_state |= PendingDeclickOut;
835                 /* we'll be called again after the declick */
836                 return;
837         }
838
839         realtime_stop (abort);
840         schedule_butler_transport_work ();
841 }
842
843 void
844 Session::start_transport ()
845 {
846         _last_roll_location = _transport_frame;
847
848         /* if record status is Enabled, move it to Recording. if its
849            already Recording, move it to Disabled. 
850         */
851
852         switch (record_status()) {
853         case Enabled:
854                 if (!punch_in) {
855                         enable_record ();
856                 }
857                 break;
858
859         case Recording:
860                 disable_record (false);
861                 break;
862
863         default:
864                 break;
865         }
866
867         if (!synced_to_jack() || _exporting) {
868                 actually_start_transport ();
869         } else {
870                 waiting_to_start = true;
871         }
872 }
873
874 void
875 Session::actually_start_transport ()
876 {
877         waiting_to_start = false;
878
879         transport_sub_state |= PendingDeclickIn;
880         _transport_speed = 1.0;
881         
882         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
883                 (*i)->realtime_set_speed ((*i)->speed(), true);
884         }
885
886         send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0);
887         
888         TransportStateChange (); /* EMIT SIGNAL */
889 }
890
891 void
892 Session::post_transport ()
893 {
894         if (post_transport_work & PostTransportAudition) {
895                 if (auditioner && auditioner->active()) {
896                         process_function = &Session::process_audition;
897                 } else {
898                         process_function = &Session::process_with_events;
899                 }
900         }
901
902         if (post_transport_work & PostTransportStop) {
903
904                 transport_sub_state = 0;
905         }
906
907         if (post_transport_work & PostTransportLocate) {
908
909                 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
910                         
911                         start_transport ();
912                         
913                 } else {
914                         transport_sub_state = 0;
915                 }
916         }
917
918         set_next_event ();
919
920         post_transport_work = PostTransportWork (0);
921 }
922
923 void
924 Session::set_rf_speed (float speed)
925 {
926         rf_speed = speed;
927         cumulative_rf_motion = 0;
928         reset_rf_scale (0);
929 }
930
931 void
932 Session::reset_rf_scale (jack_nframes_t motion)
933 {
934         cumulative_rf_motion += motion;
935
936         if (cumulative_rf_motion < 4 * _current_frame_rate) {
937                 rf_scale = 1;
938         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
939                 rf_scale = 4;
940         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
941                 rf_scale = 10;
942         } else {
943                 rf_scale = 100;
944         }
945
946         if (motion != 0) {
947                 set_dirty();
948         }
949 }
950
951 int
952 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
953 {
954         bool reverse = false;
955         bool non_rt_required = false;
956
957         if (src == _slave_type) {
958                 return 0;
959         } 
960
961         if (_transport_speed) {
962                 error << _("please stop the transport before adjusting slave settings") << endmsg;
963                 /* help out non-MVC friendly UI's by telling them the slave type changed */
964                 ControlChanged (SlaveType); /* EMIT SIGNAL */
965                 return 0;
966         }
967
968 //      if (src == JACK && Config->get_jack_time_master()) {
969 //              return -1;
970 //      }
971         
972         if (_slave) {
973                 delete _slave;
974                 _slave = 0;
975                 _slave_type = None;
976         }
977
978         if (_transport_speed < 0.0) {
979                 reverse = true;
980         }
981
982         switch (src) {
983         case None:
984                 stop_transport ();
985                 break;
986
987         case MTC:
988                 if (_mtc_port) {
989                         try {
990                                 _slave = new MTC_Slave (*this, *_mtc_port);
991                         }
992
993                         catch (failed_constructor& err) {
994                                 return -1;
995                         }
996
997                 } else {
998                         error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
999                         return -1;
1000                 }
1001                 _desired_transport_speed = _transport_speed;
1002                 break;
1003                 
1004         case JACK:
1005                 _slave = new JACK_Slave (_engine.jack());
1006                 _desired_transport_speed = _transport_speed;
1007                 break;
1008         };
1009         
1010         _slave_type = src;
1011
1012         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1013                 if (!(*i)->hidden()) {
1014                         if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1015                                 non_rt_required = true;
1016                         }
1017                         (*i)->set_slaved (_slave);
1018                 }
1019         }
1020
1021         if (reverse) {
1022                 reverse_diskstream_buffers ();
1023         }
1024
1025         if (non_rt_required) {
1026                 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1027                 schedule_butler_transport_work ();
1028         }
1029
1030         set_dirty();
1031         ControlChanged (SlaveType); /* EMIT SIGNAL */
1032         
1033         return 0;
1034 }
1035
1036 void
1037 Session::reverse_diskstream_buffers ()
1038 {
1039         post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1040         schedule_butler_transport_work ();
1041 }
1042
1043 void
1044 Session::set_diskstream_speed (Diskstream* stream, float speed)
1045 {
1046         if (stream->realtime_set_speed (speed, false)) {
1047                 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1048                 schedule_butler_transport_work ();
1049                 set_dirty ();
1050         }
1051 }
1052
1053 void
1054 Session::set_audio_range (list<AudioRange>& range)
1055 {
1056         Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1057         ev->audio_range = range;
1058         queue_event (ev);
1059 }
1060
1061 void
1062 Session::request_play_range (bool yn)
1063 {
1064         Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1065         queue_event (ev);
1066 }
1067
1068 void
1069 Session::set_play_range (bool yn)
1070 {
1071         /* Called from event-processing context */
1072
1073         if (_play_range != yn) {
1074                 _play_range = yn;
1075                 setup_auto_play ();
1076
1077                 if (!_play_range) {
1078                         /* stop transport */
1079                         Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1080                         merge_event (ev);
1081                 }
1082
1083                  ControlChanged (PlayRange); /* EMIT SIGNAL */
1084         }
1085 }
1086
1087 void
1088 Session::setup_auto_play ()
1089 {
1090         /* Called from event-processing context */
1091
1092         Event* ev;
1093         
1094         _clear_event_type (Event::RangeStop);
1095         _clear_event_type (Event::RangeLocate);
1096
1097         if (!_play_range) {
1098                 return;
1099         }
1100
1101         list<AudioRange>::size_type sz = current_audio_range.size();
1102         
1103         if (sz > 1) {
1104                 
1105                 list<AudioRange>::iterator i = current_audio_range.begin(); 
1106                 list<AudioRange>::iterator next;
1107                 
1108                 while (i != current_audio_range.end()) {
1109                         
1110                         next = i;
1111                         ++next;
1112                         
1113                         /* locating/stopping is subject to delays for declicking.
1114                          */
1115                         
1116                         jack_nframes_t requested_frame = (*i).end;
1117                         
1118                         if (requested_frame > current_block_size) {
1119                                 requested_frame -= current_block_size;
1120                         } else {
1121                                 requested_frame = 0;
1122                         }
1123                         
1124                         if (next == current_audio_range.end()) {
1125                                 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1126                         } else {
1127                                 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1128                         }
1129                         
1130                         merge_event (ev);
1131                         
1132                         i = next;
1133                 }
1134                 
1135         } else if (sz == 1) {
1136                 
1137                 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1138                 merge_event (ev);
1139                 
1140         } 
1141
1142         /* now start rolling at the right place */
1143         
1144         ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1145         merge_event (ev);
1146 }
1147
1148 void
1149 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1150 {
1151         request_stop ();
1152         Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1153         queue_event (ev);
1154         request_locate (start, true);
1155 }
1156
1157 void
1158 Session::engine_halted ()
1159 {
1160         /* there will be no more calls to process(), so
1161            we'd better clean up for ourselves, right now.
1162
1163            but first, make sure the butler is out of 
1164            the picture.
1165         */
1166
1167         g_atomic_int_set (&butler_should_do_transport_work, 0);
1168         post_transport_work = PostTransportWork (0);
1169         stop_butler ();
1170         
1171         realtime_stop (false);
1172         non_realtime_stop (false);
1173         transport_sub_state = 0;
1174
1175         TransportStateChange (); /* EMIT SIGNAL */
1176 }
1177
1178
1179 void
1180 Session::xrun_recovery ()
1181 {
1182         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1183
1184                  HaltOnXrun (); /* EMIT SIGNAL */
1185
1186                 /* it didn't actually halt, but we need
1187                    to handle things in the same way.
1188                 */
1189
1190                 engine_halted();
1191         } 
1192 }
1193
1194 void
1195 Session::update_latency_compensation (bool with_stop, bool abort)
1196 {
1197         bool update_jack = false;
1198
1199         if (_state_of_the_state & Deletion) {
1200                 return;
1201         }
1202
1203         Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1204         _worst_track_latency = 0;
1205
1206         boost::shared_ptr<RouteList> r = routes.reader ();
1207
1208         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1209                 if (with_stop) {
1210                         (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate), 
1211                                                         (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1212                 }
1213
1214                 jack_nframes_t old_latency = (*i)->signal_latency ();
1215                 jack_nframes_t track_latency = (*i)->update_total_latency ();
1216
1217                 if (old_latency != track_latency) {
1218                         update_jack = true;
1219                 }
1220                 
1221                 if (!(*i)->hidden() && ((*i)->active())) {
1222                         _worst_track_latency = max (_worst_track_latency, track_latency);
1223                 }
1224         }
1225
1226         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1227                 (*i)->set_latency_delay (_worst_track_latency);
1228         }
1229
1230         /* tell JACK to play catch up */
1231
1232         if (update_jack) {
1233                 _engine.update_total_latencies ();
1234         }
1235
1236         set_worst_io_latencies ();
1237
1238         /* reflect any changes in latencies into capture offsets
1239         */
1240         
1241         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1242                 (*i)->set_capture_offset ();
1243         }
1244 }
1245
1246 void
1247 Session::update_latency_compensation_proxy (void* ignored)
1248 {
1249         update_latency_compensation (false, false);
1250 }