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