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