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