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