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