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