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