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