Merged with trunk R708
[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
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/audio_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 using namespace PBD;
50
51 void
52 Session::request_input_change_handling ()
53 {
54         Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
55         queue_event (ev);
56 }
57
58 void
59 Session::request_slave_source (SlaveSource src, jack_nframes_t pos)
60 {
61         Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, pos, 0.0);
62
63         if (src == Session::JACK) {
64           /* could set_seamless_loop() be disposed of entirely?*/
65           set_seamless_loop (false);
66         } else {
67
68           set_seamless_loop (true);
69         }
70         ev->slave = src;
71         queue_event (ev);
72 }
73
74 void
75 Session::request_transport_speed (float speed)
76 {
77         Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
78         queue_event (ev);
79 }
80
81 void
82 Session::request_diskstream_speed (Diskstream& ds, float speed)
83 {
84         Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
85         ev->set_ptr (&ds);
86         queue_event (ev);
87 }
88
89 void
90 Session::request_stop (bool abort)
91 {
92         Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
93         queue_event (ev);
94 }
95
96 void
97 Session::request_locate (jack_nframes_t target_frame, bool with_roll)
98 {
99         Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false);
100         queue_event (ev);
101 }
102
103 void
104 Session::force_locate (jack_nframes_t target_frame, bool with_roll)
105 {
106         Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
107         queue_event (ev);
108 }
109
110 void
111 Session::request_auto_loop (bool yn)
112 {
113         Event* ev;      
114         Location *location = _locations.auto_loop_location();
115
116         if (location == 0 && yn) {
117                 error << _("Cannot loop - no loop range defined")
118                       << endmsg;
119                 return;
120         }
121
122         ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn);
123         queue_event (ev);
124
125         if (!yn && seamless_loop && transport_rolling()) {
126                 // request an immediate locate to refresh the diskstreams
127                 // after disabling looping
128                 request_locate (_transport_frame-1, true);
129         }
130 }
131
132 void
133 Session::set_seamless_loop (bool yn)
134 {
135         if (seamless_loop != yn) {
136                 seamless_loop = yn;
137
138                 if (auto_loop && transport_rolling()) {
139                         // to reset diskstreams etc
140                         request_auto_loop (true);
141                 }
142                 
143                 ControlChanged (SeamlessLoop); /* EMIT */
144         }
145 }
146
147 void
148 Session::realtime_stop (bool abort)
149 {
150         /* assume that when we start, we'll be moving forwards */
151         
152         // FIXME: where should this really be? [DR]
153         //send_full_time_code();
154         deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
155         deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
156
157         if (_transport_speed < 0.0f) {
158                 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
159         } else {
160                 post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
161         }
162
163         if (actively_recording()) {
164
165                 /* move the transport position back to where the
166                    request for a stop was noticed. we rolled
167                    past that point to pick up delayed input.
168                 */
169
170 #ifndef LEAVE_TRANSPORT_UNADJUSTED
171                 decrement_transport_position (_worst_output_latency);
172 #endif
173
174                 /* the duration change is not guaranteed to have happened, but is likely */
175
176                 post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
177         }
178
179         if (abort) {
180                 post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
181         }
182
183         _clear_event_type (Event::StopOnce);
184         _clear_event_type (Event::RangeStop);
185         _clear_event_type (Event::RangeLocate);
186
187         disable_record (true);
188
189         reset_slave_state ();
190                 
191         _transport_speed = 0;
192
193         transport_sub_state = (auto_return ? AutoReturning : 0);
194 }
195
196 void
197 Session::butler_transport_work ()
198 {
199         Glib::RWLock::ReaderLock dsm (diskstream_lock);
200         boost::shared_ptr<RouteList> r = routes.reader ();
201
202         if (post_transport_work & PostTransportCurveRealloc) {
203                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
204                         (*i)->curve_reallocate();
205                 }
206         }
207
208         if (post_transport_work & PostTransportInputChange) {
209                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
210                         (*i)->non_realtime_input_change ();
211                 }
212         }
213
214         if (post_transport_work & PostTransportSpeed) {
215                 non_realtime_set_speed ();
216         }
217
218         if (post_transport_work & PostTransportReverse) {
219
220
221                 clear_clicks();
222                 cumulative_rf_motion = 0;
223                 reset_rf_scale (0);
224
225                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
226                         if (!(*i)->hidden()) {
227                                 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
228                                         (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
229                                 }
230                                 else {
231                                         (*i)->seek (_transport_frame);
232                                 }
233                         }
234                 }
235         }
236
237         if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
238                 non_realtime_stop (post_transport_work & PostTransportAbort);
239         }
240
241         if (post_transport_work & PostTransportOverWrite) {
242                 non_realtime_overwrite ();
243         }
244
245         if (post_transport_work & PostTransportAudition) {
246                 non_realtime_set_audition ();
247         }
248
249         g_atomic_int_dec_and_test (&butler_should_do_transport_work);
250 }
251
252 void
253 Session::non_realtime_set_speed ()
254 {
255         Glib::RWLock::ReaderLock lm (diskstream_lock);
256
257         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
258                 (*i)->non_realtime_set_speed ();
259         }
260 }
261
262 void
263 Session::non_realtime_overwrite ()
264 {
265         Glib::RWLock::ReaderLock lm (diskstream_lock);
266
267         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
268                 if ((*i)->pending_overwrite) {
269                         (*i)->overwrite_existing_buffers ();
270                 }
271         }
272 }
273
274 void
275 Session::non_realtime_stop (bool abort)
276 {
277         struct tm* now;
278         time_t     xnow;
279         bool       did_record;
280         
281         did_record = false;
282         
283         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
284                 if ((*i)->get_captured_frames () != 0) {
285                         did_record = true;
286                         break;
287                 }
288         }
289
290         /* stop and locate are merged here because they share a lot of common stuff */
291         
292         time (&xnow);
293         now = localtime (&xnow);
294
295         if (auditioner) {
296                 auditioner->cancel_audition ();
297         }
298
299         clear_clicks();
300         cumulative_rf_motion = 0;
301         reset_rf_scale (0);
302
303         if (did_record) {
304                 begin_reversible_command ("capture");
305                 
306                 Location* loc = _locations.end_location();
307                 bool change_end = false;
308
309                 if (_transport_frame < loc->end()) {
310
311                         /* stopped recording before current end */
312
313                         if (_end_location_is_free) {
314
315                                 /* first capture for this session, move end back to where we are */
316
317                                 change_end = true;
318                         } 
319
320                 } else if (_transport_frame > loc->end()) {
321                         
322                         /* stopped recording after the current end, extend it */
323
324                         change_end = true;
325                 }
326                 
327                 if (change_end) {
328                         add_undo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), loc->end())));
329                         add_redo (sigc::retype_return<void>(sigc::bind (mem_fun (*loc, &Location::set_end), _transport_frame)));
330                 }
331
332                 _end_location_is_free = false;
333                 _have_captured = true;
334         }
335
336         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
337                 (*i)->transport_stopped (*now, xnow, abort);
338         }
339         
340         boost::shared_ptr<RouteList> r = routes.reader ();
341
342         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
343                 if (!(*i)->hidden()) {
344                         (*i)->set_pending_declick (0);
345                 }
346         }
347
348         if (did_record) {
349                 commit_reversible_command ();
350         }       
351
352         if (_engine.running()) {
353                 update_latency_compensation (true, abort);
354         }
355
356         if (auto_return || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
357
358                 if (pending_locate_flush) {
359                         flush_all_redirects ();
360                 }
361
362                 if ((auto_return || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
363
364                         _transport_frame = last_stop_frame;
365
366                         if (synced_to_jack()) {
367                                 _engine.transport_locate (_transport_frame);
368                         }
369                 } 
370
371 #ifndef LEAVE_TRANSPORT_UNADJUSTED
372         }
373 #endif
374
375                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
376                         if (!(*i)->hidden()) {
377                                 if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
378                                         (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
379                                 }
380                                 else {
381                                         (*i)->seek (_transport_frame);
382                                 }
383                         }
384                 }
385
386                 //FIXME
387                 //deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
388
389 #ifdef LEAVE_TRANSPORT_UNADJUSTED
390         }
391 #endif
392
393         last_stop_frame = _transport_frame;
394
395         if (did_record) {
396
397                 /* XXX its a little odd that we're doing this here
398                    when realtime_stop(), which has already executed,
399                    will have done this.
400                 */
401
402                 if (!Config->get_latched_record_enable()) {
403                         g_atomic_int_set (&_record_status, Disabled);
404                 } else {
405                         g_atomic_int_set (&_record_status, Enabled);
406                 }
407                 RecordStateChanged (); /* emit signal */
408         }
409         
410         if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
411                 /* capture start has been changed, so save pending state */
412                 save_state ("", true);
413         }
414
415         /* always try to get rid of this */
416
417         remove_pending_capture_state ();
418         
419         /* save the current state of things if appropriate */
420
421         if (did_record) {
422                 save_state (_current_snapshot_name);
423         }
424
425         if (post_transport_work & PostTransportDuration) {
426                 DurationChanged (); /* EMIT SIGNAL */
427         }
428
429         if (post_transport_work & PostTransportStop) { 
430                 _play_range = false;
431
432                 /* do not turn off autoloop on stop */
433
434         }
435
436         PositionChanged (_transport_frame); /* EMIT SIGNAL */
437         TransportStateChange (); /* EMIT SIGNAL */
438
439         /* and start it up again if relevant */
440
441         if ((post_transport_work & PostTransportLocate) && _slave_type == None && pending_locate_roll) {
442                 request_transport_speed (1.0);
443                 pending_locate_roll = false;
444         }
445 }
446
447 void
448 Session::check_declick_out ()
449 {
450         bool locate_required = transport_sub_state & PendingLocate;
451
452         /* this is called after a process() iteration. if PendingDeclickOut was set,
453            it means that we were waiting to declick the output (which has just been
454            done) before doing something else. this is where we do that "something else".
455            
456            note: called from the audio thread.
457         */
458
459         if (transport_sub_state & PendingDeclickOut) {
460
461                 if (locate_required) {
462                         start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
463                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
464                 } else {
465                         stop_transport (pending_abort);
466                         transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
467                 }
468         }
469 }
470
471 void
472 Session::set_auto_loop (bool yn)
473 {
474         /* Called from event-handling context */
475         
476         if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
477                 return;
478         }
479         
480         set_dirty();
481
482         if (yn && seamless_loop && synced_to_jack()) {
483                 warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
484                              "Recommend changing the configured options")
485                         << endmsg;
486                 return;
487         }
488
489         
490         if ((auto_loop = yn)) {
491
492                 Location *loc;
493
494                 
495                 if ((loc = _locations.auto_loop_location()) != 0) {
496
497                         if (seamless_loop) {
498                                 // set all diskstreams to use internal looping
499                                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
500                                         if (!(*i)->hidden()) {
501                                                 (*i)->set_loop (loc);
502                                         }
503                                 }
504                         }
505                         else {
506                                 // set all diskstreams to NOT use internal looping
507                                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
508                                         if (!(*i)->hidden()) {
509                                                 (*i)->set_loop (0);
510                                         }
511                                 }
512                         }
513                         
514                         /* stick in the loop event */
515                         
516                         Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
517                         merge_event (event);
518
519                         /* locate to start of loop and roll if current pos is outside of the loop range */
520                         if (_transport_frame < loc->start() || _transport_frame > loc->end()) {
521                                 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
522                                 merge_event (event);
523                         }
524                         else {
525                                 // locate to current position (+ 1 to force reload)
526                                 event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack());
527                                 merge_event (event);
528                         }
529                 }
530
531
532
533         } else {
534                 clear_events (Event::AutoLoop);
535
536                 // set all diskstreams to NOT use internal looping
537                 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
538                         if (!(*i)->hidden()) {
539                                 (*i)->set_loop (0);
540                         }
541                 }
542                 
543         }
544         
545         ControlChanged (AutoLoop); /* EMIT SIGNAL */
546 }
547
548 void
549 Session::flush_all_redirects ()
550 {
551         boost::shared_ptr<RouteList> r = routes.reader ();
552
553         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
554                 (*i)->flush_redirects ();
555         }
556 }
557
558 void
559 Session::start_locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
560 {
561         if (synced_to_jack()) {
562
563                 float sp;
564                 jack_nframes_t pos;
565
566                 _slave->speed_and_position (sp, pos);
567
568                 if (target_frame != pos) {
569
570                         /* tell JACK to change transport position, and we will
571                            follow along later in ::follow_slave()
572                         */
573
574                         _engine.transport_locate (target_frame);
575
576                         if (sp != 1.0f && with_roll) {
577                                 _engine.transport_start ();
578                         }
579
580                 }
581
582         } else {
583
584                 locate (target_frame, with_roll, with_flush, with_loop);
585         }
586 }
587
588 void
589 Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
590 {
591         if (actively_recording()) {
592                 return;
593         }
594
595         if (_transport_frame == target_frame && !loop_changing && !with_loop) {
596                 if (with_roll) {
597                         set_transport_speed (1.0, false);
598                 }
599                 loop_changing = false;
600                 return;
601         }
602
603         // Update SMPTE time
604         // [DR] FIXME: find out exactly where this should go below
605         _transport_frame = target_frame;
606         smpte_time(_transport_frame, transmitting_smpte_time);
607         outbound_mtc_smpte_frame = _transport_frame;
608         next_quarter_frame_to_send = 0;
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                 Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
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                         Glib::RWLock::ReaderLock dsm (diskstream_lock);
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                         Glib::RWLock::ReaderLock dsm (diskstream_lock);
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                         Glib::RWLock::ReaderLock dsm (diskstream_lock);
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                         Glib::RWLock::ReaderLock dsm (diskstream_lock);
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         deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame);
893
894         TransportStateChange (); /* EMIT SIGNAL */
895 }
896
897 /** Do any transport work in the audio thread that needs to be done after the
898  * transport thread is finished.  Audio thread, realtime safe.
899  */
900 void
901 Session::post_transport ()
902 {
903         if (post_transport_work & PostTransportAudition) {
904                 if (auditioner && auditioner->active()) {
905                         process_function = &Session::process_audition;
906                 } else {
907                         process_function = &Session::process_with_events;
908                 }
909         }
910
911         if (post_transport_work & PostTransportStop) {
912
913                 transport_sub_state = 0;
914         }
915
916         if (post_transport_work & PostTransportLocate) {
917
918                 if ((auto_play && !_exporting) || (post_transport_work & PostTransportRoll)) {
919                         
920                         start_transport ();
921                         
922                 } else {
923                         transport_sub_state = 0;
924                 }
925         }
926
927         set_next_event ();
928
929         post_transport_work = PostTransportWork (0);
930 }
931
932 void
933 Session::set_rf_speed (float speed)
934 {
935         rf_speed = speed;
936         cumulative_rf_motion = 0;
937         reset_rf_scale (0);
938 }
939
940 void
941 Session::reset_rf_scale (jack_nframes_t motion)
942 {
943         cumulative_rf_motion += motion;
944
945         if (cumulative_rf_motion < 4 * _current_frame_rate) {
946                 rf_scale = 1;
947         } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
948                 rf_scale = 4;
949         } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
950                 rf_scale = 10;
951         } else {
952                 rf_scale = 100;
953         }
954
955         if (motion != 0) {
956                 set_dirty();
957         }
958 }
959
960 int
961 Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
962 {
963         bool reverse = false;
964         bool non_rt_required = false;
965
966         if (src == _slave_type) {
967                 return 0;
968         } 
969
970         if (_transport_speed) {
971                 error << _("please stop the transport before adjusting slave settings") << endmsg;
972                 /* help out non-MVC friendly UI's by telling them the slave type changed */
973                 ControlChanged (SlaveType); /* EMIT SIGNAL */
974                 return 0;
975         }
976
977 //      if (src == JACK && Config->get_jack_time_master()) {
978 //              return -1;
979 //      }
980         
981         if (_slave) {
982                 delete _slave;
983                 _slave = 0;
984                 _slave_type = None;
985         }
986
987         if (_transport_speed < 0.0) {
988                 reverse = true;
989         }
990
991         switch (src) {
992         case None:
993                 stop_transport ();
994                 break;
995
996         case MTC:
997                 if (_mtc_port) {
998                         try {
999                                 _slave = new MTC_Slave (*this, *_mtc_port);
1000                         }
1001
1002                         catch (failed_constructor& err) {
1003                                 return -1;
1004                         }
1005
1006                 } else {
1007                         error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
1008                         return -1;
1009                 }
1010                 _desired_transport_speed = _transport_speed;
1011                 break;
1012                 
1013         case JACK:
1014                 _slave = new JACK_Slave (_engine.jack());
1015                 _desired_transport_speed = _transport_speed;
1016                 break;
1017         };
1018         
1019         _slave_type = src;
1020
1021         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1022                 if (!(*i)->hidden()) {
1023                         if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
1024                                 non_rt_required = true;
1025                         }
1026                         (*i)->set_slaved (_slave);
1027                 }
1028         }
1029
1030         if (reverse) {
1031                 reverse_diskstream_buffers ();
1032         }
1033
1034         if (non_rt_required) {
1035                 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1036                 schedule_butler_transport_work ();
1037         }
1038
1039         set_dirty();
1040         ControlChanged (SlaveType); /* EMIT SIGNAL */
1041         
1042         return 0;
1043 }
1044
1045 void
1046 Session::reverse_diskstream_buffers ()
1047 {
1048         post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
1049         schedule_butler_transport_work ();
1050 }
1051
1052 void
1053 Session::set_diskstream_speed (Diskstream* stream, float speed)
1054 {
1055         if (stream->realtime_set_speed (speed, false)) {
1056                 post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
1057                 schedule_butler_transport_work ();
1058                 set_dirty ();
1059         }
1060 }
1061
1062 void
1063 Session::set_audio_range (list<AudioRange>& range)
1064 {
1065         Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
1066         ev->audio_range = range;
1067         queue_event (ev);
1068 }
1069
1070 void
1071 Session::request_play_range (bool yn)
1072 {
1073         Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn);
1074         queue_event (ev);
1075 }
1076
1077 void
1078 Session::set_play_range (bool yn)
1079 {
1080         /* Called from event-processing context */
1081
1082         if (_play_range != yn) {
1083                 _play_range = yn;
1084                 setup_auto_play ();
1085
1086                 if (!_play_range) {
1087                         /* stop transport */
1088                         Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
1089                         merge_event (ev);
1090                 }
1091
1092                  ControlChanged (PlayRange); /* EMIT SIGNAL */
1093         }
1094 }
1095
1096 void
1097 Session::setup_auto_play ()
1098 {
1099         /* Called from event-processing context */
1100
1101         Event* ev;
1102         
1103         _clear_event_type (Event::RangeStop);
1104         _clear_event_type (Event::RangeLocate);
1105
1106         if (!_play_range) {
1107                 return;
1108         }
1109
1110         list<AudioRange>::size_type sz = current_audio_range.size();
1111         
1112         if (sz > 1) {
1113                 
1114                 list<AudioRange>::iterator i = current_audio_range.begin(); 
1115                 list<AudioRange>::iterator next;
1116                 
1117                 while (i != current_audio_range.end()) {
1118                         
1119                         next = i;
1120                         ++next;
1121                         
1122                         /* locating/stopping is subject to delays for declicking.
1123                          */
1124                         
1125                         jack_nframes_t requested_frame = (*i).end;
1126                         
1127                         if (requested_frame > current_block_size) {
1128                                 requested_frame -= current_block_size;
1129                         } else {
1130                                 requested_frame = 0;
1131                         }
1132                         
1133                         if (next == current_audio_range.end()) {
1134                                 ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
1135                         } else {
1136                                 ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
1137                         }
1138                         
1139                         merge_event (ev);
1140                         
1141                         i = next;
1142                 }
1143                 
1144         } else if (sz == 1) {
1145                 
1146                 ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
1147                 merge_event (ev);
1148                 
1149         } 
1150
1151         /* now start rolling at the right place */
1152         
1153         ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
1154         merge_event (ev);
1155 }
1156
1157 void
1158 Session::request_bounded_roll (jack_nframes_t start, jack_nframes_t end)
1159 {
1160         request_stop ();
1161         Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0);
1162         queue_event (ev);
1163         request_locate (start, true);
1164 }
1165
1166 void
1167 Session::engine_halted ()
1168 {
1169         /* there will be no more calls to process(), so
1170            we'd better clean up for ourselves, right now.
1171
1172            but first, make sure the butler is out of 
1173            the picture.
1174         */
1175
1176         g_atomic_int_set (&butler_should_do_transport_work, 0);
1177         post_transport_work = PostTransportWork (0);
1178         stop_butler ();
1179         
1180         realtime_stop (false);
1181         non_realtime_stop (false);
1182         transport_sub_state = 0;
1183
1184         TransportStateChange (); /* EMIT SIGNAL */
1185 }
1186
1187
1188 void
1189 Session::xrun_recovery ()
1190 {
1191         if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1192
1193                  HaltOnXrun (); /* EMIT SIGNAL */
1194
1195                 /* it didn't actually halt, but we need
1196                    to handle things in the same way.
1197                 */
1198
1199                 engine_halted();
1200         } 
1201 }
1202
1203 void
1204 Session::update_latency_compensation (bool with_stop, bool abort)
1205 {
1206         bool update_jack = false;
1207
1208         if (_state_of_the_state & Deletion) {
1209                 return;
1210         }
1211
1212         Glib::RWLock::ReaderLock lm2 (diskstream_lock);
1213         _worst_track_latency = 0;
1214
1215         boost::shared_ptr<RouteList> r = routes.reader ();
1216
1217         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1218                 if (with_stop) {
1219                         (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate), 
1220                                                         (!(post_transport_work & PostTransportLocate) || pending_locate_flush));
1221                 }
1222
1223                 jack_nframes_t old_latency = (*i)->signal_latency ();
1224                 jack_nframes_t track_latency = (*i)->update_total_latency ();
1225
1226                 if (old_latency != track_latency) {
1227                         update_jack = true;
1228                 }
1229                 
1230                 if (!(*i)->hidden() && ((*i)->active())) {
1231                         _worst_track_latency = max (_worst_track_latency, track_latency);
1232                 }
1233         }
1234
1235         for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1236                 (*i)->set_latency_delay (_worst_track_latency);
1237         }
1238
1239         /* tell JACK to play catch up */
1240
1241         if (update_jack) {
1242                 _engine.update_total_latencies ();
1243         }
1244
1245         set_worst_io_latencies ();
1246
1247         /* reflect any changes in latencies into capture offsets
1248         */
1249         
1250         for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1251                 (*i)->set_capture_offset ();
1252         }
1253 }
1254
1255 void
1256 Session::update_latency_compensation_proxy (void* ignored)
1257 {
1258         update_latency_compensation (false, false);
1259 }