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