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