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