full compilation and linking (coding not finished, will not run)
[ardour.git] / libs / ardour / audioengine.cc
1 /*
2     Copyright (C) 2002 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 */
19
20 #include <unistd.h>
21 #include <cerrno>
22 #include <vector>
23 #include <exception>
24 #include <stdexcept>
25 #include <sstream>
26
27 #include <glibmm/timer.h>
28 #include <glibmm/pattern.h>
29 #include <glibmm/module.h>
30
31 #include "pbd/epa.h"
32 #include "pbd/file_utils.h"
33 #include "pbd/pthread_utils.h"
34 #include "pbd/stacktrace.h"
35 #include "pbd/unknown_type.h"
36
37 #include <jack/weakjack.h>
38
39 #include "midi++/port.h"
40 #include "midi++/jack_midi_port.h"
41 #include "midi++/mmc.h"
42 #include "midi++/manager.h"
43
44 #include "ardour/audio_port.h"
45 #include "ardour/audio_backend.h"
46 #include "ardour/audioengine.h"
47 #include "ardour/backend_search_path.h"
48 #include "ardour/buffer.h"
49 #include "ardour/cycle_timer.h"
50 #include "ardour/internal_send.h"
51 #include "ardour/meter.h"
52 #include "ardour/midi_port.h"
53 #include "ardour/port.h"
54 #include "ardour/process_thread.h"
55 #include "ardour/session.h"
56
57 #include "i18n.h"
58
59 using namespace std;
60 using namespace ARDOUR;
61 using namespace PBD;
62
63 gint AudioEngine::m_meter_exit;
64 AudioEngine* AudioEngine::_instance = 0;
65
66 AudioEngine::AudioEngine (const std::string& bcn, const std::string& bsu)
67         : session_remove_pending (false)
68         , session_removal_countdown (-1)
69         , monitor_check_interval (INT32_MAX)
70         , last_monitor_check (0)
71         , _processed_frames (0)
72         , _freewheeling (false)
73         , _pre_freewheel_mmc_enabled (false)
74         , _usecs_per_cycle (0)
75         , port_remove_in_progress (false)
76         , m_meter_thread (0)
77         , _main_thread (0)
78         , backend_client_name (bcn)
79         , backend_session_uuid (bsu)
80 {
81         g_atomic_int_set (&m_meter_exit, 0);
82 }
83
84 AudioEngine::~AudioEngine ()
85 {
86         drop_backend ();
87
88         config_connection.disconnect ();
89
90         {
91                 Glib::Threads::Mutex::Lock tm (_process_lock);
92                 session_removed.signal ();
93                 stop_metering_thread ();
94         }
95 }
96
97 AudioEngine*
98 AudioEngine::create (const std::string& bcn, const std::string& bsu)
99 {
100         if (_instance) {
101                 return _instance;
102         }
103         return new AudioEngine (bcn, bsu);
104 }
105
106 void
107 _thread_init_callback (void * /*arg*/)
108 {
109         /* make sure that anybody who needs to know about this thread
110            knows about it.
111         */
112
113         pthread_set_name (X_("audioengine"));
114
115         PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("Audioengine"), 4096);
116         PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("Audioengine"), 128);
117
118         SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
119
120         MIDI::JackMIDIPort::set_process_thread (pthread_self());
121 }
122
123
124
125 void
126 AudioEngine::split_cycle (pframes_t offset)
127 {
128         /* caller must hold process lock */
129
130         Port::increment_global_port_buffer_offset (offset);
131
132         /* tell all Ports that we're going to start a new (split) cycle */
133
134         boost::shared_ptr<Ports> p = ports.reader();
135
136         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
137                 i->second->cycle_split ();
138         }
139 }
140
141 int
142 AudioEngine::sample_rate_change (pframes_t nframes)
143 {
144         /* check for monitor input change every 1/10th of second */
145
146         monitor_check_interval = nframes / 10;
147         last_monitor_check = 0;
148
149         if (_session) {
150                 _session->set_frame_rate (nframes);
151         }
152
153         SampleRateChanged (nframes); /* EMIT SIGNAL */
154
155         return 0;
156 }
157
158 int 
159 AudioEngine::buffer_size_change (pframes_t bufsiz)
160 {
161         if (_session) {
162                 _session->set_block_size (bufsiz);
163                 last_monitor_check = 0;
164         }
165
166         return 0;
167 }
168
169 /** Method called by our ::process_thread when there is work to be done.
170  *  @param nframes Number of frames to process.
171  */
172 int
173 AudioEngine::process_callback (pframes_t nframes)
174 {
175         Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
176
177         PT_TIMING_REF;
178         PT_TIMING_CHECK (1);
179
180         /// The number of frames that will have been processed when we've finished
181         pframes_t next_processed_frames;
182
183         /* handle wrap around of total frames counter */
184
185         if (max_framepos - _processed_frames < nframes) {
186                 next_processed_frames = nframes - (max_framepos - _processed_frames);
187         } else {
188                 next_processed_frames = _processed_frames + nframes;
189         }
190
191         if (!tm.locked()) {
192                 /* return having done nothing */
193                 _processed_frames = next_processed_frames;
194                 return 0;
195         }
196
197         if (session_remove_pending) {
198
199                 /* perform the actual session removal */
200
201                 if (session_removal_countdown < 0) {
202
203                         /* fade out over 1 second */
204                         session_removal_countdown = _frame_rate/2;
205                         session_removal_gain = 1.0;
206                         session_removal_gain_step = 1.0/session_removal_countdown;
207
208                 } else if (session_removal_countdown > 0) {
209
210                         /* we'll be fading audio out.
211                            
212                            if this is the last time we do this as part 
213                            of session removal, do a MIDI panic now
214                            to get MIDI stopped. This relies on the fact
215                            that "immediate data" (aka "out of band data") from
216                            MIDI tracks is *appended* after any other data, 
217                            so that it emerges after any outbound note ons, etc.
218                         */
219
220                         if (session_removal_countdown <= nframes) {
221                                 _session->midi_panic ();
222                         }
223
224                 } else {
225                         /* fade out done */
226                         _session = 0;
227                         session_removal_countdown = -1; // reset to "not in progress"
228                         session_remove_pending = false;
229                         session_removed.signal(); // wakes up thread that initiated session removal
230                 }
231         }
232
233         if (_session == 0) {
234
235                 if (!_freewheeling) {
236                         MIDI::Manager::instance()->cycle_start(nframes);
237                         MIDI::Manager::instance()->cycle_end();
238                 }
239
240                 _processed_frames = next_processed_frames;
241
242                 return 0;
243         }
244
245         /* tell all relevant objects that we're starting a new cycle */
246
247         InternalSend::CycleStart (nframes);
248         Port::set_global_port_buffer_offset (0);
249         Port::set_cycle_framecnt (nframes);
250
251         /* tell all Ports that we're starting a new cycle */
252
253         boost::shared_ptr<Ports> p = ports.reader();
254
255         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
256                 i->second->cycle_start (nframes);
257         }
258
259         /* test if we are freewheeling and there are freewheel signals connected.
260            ardour should act normally even when freewheeling unless /it/ is
261            exporting 
262         */
263
264         if (_freewheeling && !Freewheel.empty()) {
265
266                 Freewheel (nframes);
267
268         } else {
269                 MIDI::Manager::instance()->cycle_start(nframes);
270
271                 if (_session) {
272                         _session->process (nframes);
273                 }
274
275                 MIDI::Manager::instance()->cycle_end();
276         }
277
278         if (_freewheeling) {
279                 return 0;
280         }
281
282         if (!_running) {
283                 _processed_frames = next_processed_frames;
284                 return 0;
285         }
286
287         if (last_monitor_check + monitor_check_interval < next_processed_frames) {
288
289                 boost::shared_ptr<Ports> p = ports.reader();
290
291                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
292
293                         bool x;
294
295                         if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
296                                 i->second->set_last_monitor (x);
297                                 /* XXX I think this is dangerous, due to
298                                    a likely mutex in the signal handlers ...
299                                 */
300                                 i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
301                         }
302                 }
303                 last_monitor_check = next_processed_frames;
304         }
305
306         if (_session->silent()) {
307
308                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
309
310                         if (i->second->sends_output()) {
311                                 i->second->get_buffer(nframes).silence(nframes);
312                         }
313                 }
314         }
315
316         if (session_remove_pending && session_removal_countdown) {
317
318                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
319
320                         if (i->second->sends_output()) {
321
322                                 boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
323                                 if (ap) {
324                                         Sample* s = ap->engine_get_whole_audio_buffer ();
325                                         gain_t g = session_removal_gain;
326                                         
327                                         for (pframes_t n = 0; n < nframes; ++n) {
328                                                 *s++ *= g;
329                                                 g -= session_removal_gain_step;
330                                         }
331                                 }
332                         }
333                 }
334                 
335                 if (session_removal_countdown > nframes) {
336                         session_removal_countdown -= nframes;
337                 } else {
338                         session_removal_countdown = 0;
339                 }
340
341                 session_removal_gain -= (nframes * session_removal_gain_step);
342         }
343
344         // Finalize ports
345
346         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
347                 i->second->cycle_end (nframes);
348         }
349
350         _processed_frames = next_processed_frames;
351
352         PT_TIMING_CHECK (2);
353         
354         return 0;
355 }
356
357
358 void
359 AudioEngine::stop_metering_thread ()
360 {
361         if (m_meter_thread) {
362                 g_atomic_int_set (&m_meter_exit, 1);
363                 m_meter_thread->join ();
364                 m_meter_thread = 0;
365         }
366 }
367
368 void
369 AudioEngine::start_metering_thread ()
370 {
371         if (m_meter_thread == 0) {
372                 g_atomic_int_set (&m_meter_exit, 0);
373                 m_meter_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::meter_thread, this));
374         }
375 }
376
377 void
378 AudioEngine::meter_thread ()
379 {
380         pthread_set_name (X_("meter"));
381
382         while (true) {
383                 Glib::usleep (10000); /* 1/100th sec interval */
384                 if (g_atomic_int_get(&m_meter_exit)) {
385                         break;
386                 }
387                 Metering::Meter ();
388         }
389 }
390
391 void
392 AudioEngine::set_session (Session *s)
393 {
394         Glib::Threads::Mutex::Lock pl (_process_lock);
395
396         SessionHandlePtr::set_session (s);
397
398         if (_session) {
399
400                 start_metering_thread ();
401
402                 pframes_t blocksize = _backend->buffer_size ();
403
404                 /* page in as much of the session process code as we
405                    can before we really start running.
406                 */
407
408                 boost::shared_ptr<Ports> p = ports.reader();
409
410                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
411                         i->second->cycle_start (blocksize);
412                 }
413
414                 _session->process (blocksize);
415                 _session->process (blocksize);
416                 _session->process (blocksize);
417                 _session->process (blocksize);
418                 _session->process (blocksize);
419                 _session->process (blocksize);
420                 _session->process (blocksize);
421                 _session->process (blocksize);
422
423                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
424                         i->second->cycle_end (blocksize);
425                 }
426         }
427 }
428
429 void
430 AudioEngine::remove_session ()
431 {
432         Glib::Threads::Mutex::Lock lm (_process_lock);
433
434         if (_running) {
435
436                 stop_metering_thread ();
437
438                 if (_session) {
439                         session_remove_pending = true;
440                         session_removed.wait(_process_lock);
441                 }
442
443         } else {
444                 SessionHandlePtr::set_session (0);
445         }
446
447         remove_all_ports ();
448 }
449
450
451 void
452 AudioEngine::died ()
453 {
454         /* called from a signal handler for SIGPIPE */
455
456         stop_metering_thread ();
457
458         _running = false;
459         _buffer_size = 0;
460         _frame_rate = 0;
461 }
462
463 int
464 AudioEngine::reset_timebase ()
465 {
466         if (_session) {
467                 if (_session->config.get_jack_time_master()) {
468                         _backend->set_time_master (true);
469                 } else {
470                         _backend->set_time_master (false);
471                 }
472         }
473         return 0;
474 }
475
476
477 void
478 AudioEngine::destroy ()
479 {
480         delete _instance;
481         _instance = 0;
482 }
483
484 int
485 AudioEngine::discover_backends ()
486 {
487         vector<std::string> backend_modules;
488
489         _backends.clear ();
490
491         Glib::PatternSpec so_extension_pattern("*.so");
492         Glib::PatternSpec dylib_extension_pattern("*.dylib");
493
494         find_matching_files_in_search_path (backend_search_path (),
495                                             so_extension_pattern, backend_modules);
496
497         find_matching_files_in_search_path (backend_search_path (),
498                                             dylib_extension_pattern, backend_modules);
499
500         DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1"), backend_search_path().to_string()));
501
502         for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
503
504                 AudioBackendInfo* info;
505
506                 if ((info = backend_discover (*i)) != 0) {
507                         _backends.insert (make_pair (info->name, info));
508                 }
509         }
510
511         return _backends.size();
512 }
513
514 AudioBackendInfo*
515 AudioEngine::backend_discover (const string& path)
516 {
517         Glib::Module* module = new Glib::Module(path);
518         AudioBackendInfo* info;
519         void* sym = 0;
520
521         if (!module) {
522                 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
523                                 Glib::Module::get_last_error()) << endmsg;
524                 delete module;
525                 return 0;
526         }
527
528         if (!module->get_symbol("descriptor", sym)) {
529                 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor."), path) << endmsg;
530                 error << Glib::Module::get_last_error() << endmsg;
531                 delete module;
532                 return 0;
533         }
534
535         info = (AudioBackendInfo*) sym;
536
537         return info;
538 }
539
540 vector<string>
541 AudioEngine::available_backends() const
542 {
543         vector<string> r;
544         
545         for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
546                 r.push_back (i->first);
547         }
548
549         return r;
550 }
551
552 string
553 AudioEngine::current_backend_name() const
554 {
555         if (_backend) {
556                 return _backend->name();
557         } 
558         return string();
559 }
560
561 void
562 AudioEngine::drop_backend ()
563 {
564         if (_backend) {
565                 _backend->stop ();
566                 _backend.reset ();
567         }
568 }
569
570 int
571 AudioEngine::set_backend (const std::string& name)
572 {
573         BackendMap::iterator b = _backends.find (name);
574
575         if (b == _backends.end()) {
576                 return -1;
577         }
578
579         drop_backend ();
580
581         try {
582
583                 _backend = b->second->backend_factory (*this);
584                 _impl = b->second->portengine_factory (*this);
585
586         } catch (...) {
587                 error << string_compose (_("Could not create backend for %1"), name) << endmsg;
588                 return -1;
589         }
590
591         return 0;
592 }
593
594 /* BACKEND PROXY WRAPPERS */
595
596 int
597 AudioEngine::start ()
598 {
599         if (!_backend) {
600                 return -1;
601         }
602
603         if (!_running) {
604
605                 if (_session) {
606                         BootMessage (_("Connect session to engine"));
607                         _session->set_frame_rate (_backend->sample_rate());
608                 }
609
610                 _processed_frames = 0;
611                 last_monitor_check = 0;
612
613                 if (_backend->start() == 0) {
614                         _running = true;
615                         _has_run = true;
616                         last_monitor_check = 0;
617
618                         if (_session && _session->config.get_jack_time_master()) {
619                                 _backend->set_time_master (true);
620                         }
621
622                         Running(); /* EMIT SIGNAL */
623                 } else {
624                         /* should report error? */
625                 }
626         }
627                 
628         return _running ? 0 : -1;
629 }
630
631 int
632 AudioEngine::stop ()
633 {
634         if (!_backend) {
635                 return 0;
636         }
637
638         Glib::Threads::Mutex::Lock lm (_process_lock);
639
640         if (_backend->stop () == 0) {
641                 _running = false;
642                 stop_metering_thread ();
643
644                 Stopped (); /* EMIT SIGNAL */
645
646                 return 0;
647         }
648
649         return -1;
650 }
651
652 int
653 AudioEngine::pause ()
654 {
655         if (!_backend) {
656                 return 0;
657         }
658         
659         if (_backend->pause () == 0) {
660                 _running = false;
661                 Stopped(); /* EMIT SIGNAL */
662                 return 0;
663         }
664
665         return -1;
666 }
667
668 int
669 AudioEngine::freewheel (bool start_stop)
670 {
671         if (!_backend) {
672                 return -1;
673         }
674
675         /* _freewheeling will be set when first Freewheel signal occurs */
676
677         return _backend->freewheel (start_stop);
678 }
679
680 float
681 AudioEngine::get_cpu_load() const 
682 {
683         if (!_backend) {
684                 return 0.0;
685         }
686         return _backend->cpu_load ();
687 }
688
689 bool
690 AudioEngine::is_realtime() const 
691 {
692         if (!_backend) {
693                 return false;
694         }
695
696         return _backend->is_realtime();
697 }
698
699 bool
700 AudioEngine::connected() const 
701 {
702         if (!_backend) {
703                 return false;
704         }
705
706         return _backend->connected();
707 }
708
709 void
710 AudioEngine::transport_start ()
711 {
712         if (!_backend) {
713                 return;
714         }
715         return _backend->transport_start ();
716 }
717
718 void
719 AudioEngine::transport_stop ()
720 {
721         if (!_backend) {
722                 return;
723         }
724         return _backend->transport_stop ();
725 }
726
727 TransportState
728 AudioEngine::transport_state ()
729 {
730         if (!_backend) {
731                 return TransportStopped;
732         }
733         return _backend->transport_state ();
734 }
735
736 void
737 AudioEngine::transport_locate (framepos_t pos)
738 {
739         if (!_backend) {
740                 return;
741         }
742         return _backend->transport_locate (pos);
743 }
744
745 framepos_t
746 AudioEngine::transport_frame()
747 {
748         if (!_backend) {
749                 return 0;
750         }
751         return _backend->transport_frame ();
752 }
753
754 framecnt_t
755 AudioEngine::sample_rate () const
756 {
757         if (!_backend) {
758                 return 0;
759         }
760         return _backend->sample_rate ();
761 }
762
763 pframes_t
764 AudioEngine::samples_per_cycle () const
765 {
766         if (!_backend) {
767                 return 0;
768         }
769         return _backend->buffer_size ();
770 }
771
772 int
773 AudioEngine::usecs_per_cycle () const
774 {
775         if (!_backend) {
776                 return -1;
777         }
778         return _backend->usecs_per_cycle ();
779 }
780
781 size_t
782 AudioEngine::raw_buffer_size (DataType t)
783 {
784         if (!_backend) {
785                 return -1;
786         }
787         return _backend->raw_buffer_size (t);
788 }
789
790 pframes_t
791 AudioEngine::sample_time ()
792 {
793         if (!_backend) {
794                 return 0;
795         }
796         return _backend->sample_time ();
797 }
798
799 pframes_t
800 AudioEngine::sample_time_at_cycle_start ()
801 {
802         if (!_backend) {
803                 return 0;
804         }
805         return _backend->sample_time_at_cycle_start ();
806 }
807
808 pframes_t
809 AudioEngine::samples_since_cycle_start ()
810 {
811         if (!_backend) {
812                 return 0;
813         }
814         return _backend->samples_since_cycle_start ();
815 }
816
817 bool
818 AudioEngine::get_sync_offset (pframes_t& offset) const
819 {
820         if (!_backend) {
821                 return false;
822         }
823         return _backend->get_sync_offset (offset);
824 }
825
826 int
827 AudioEngine::create_process_thread (boost::function<void()> func, pthread_t* thr, size_t stacksize)
828 {
829         if (!_backend) {
830                 return -1;
831         }
832         return _backend->create_process_thread (func, thr, stacksize);
833 }
834
835
836 int
837 AudioEngine::set_device_name (const std::string& name)
838 {
839         if (!_backend) {
840                 return -1;
841         }
842         return _backend->set_device_name  (name);
843 }
844
845 int
846 AudioEngine::set_sample_rate (float sr)
847 {
848         if (!_backend) {
849                 return -1;
850         }
851         return _backend->set_sample_rate  (sr);
852 }
853
854 int
855 AudioEngine::set_buffer_size (uint32_t bufsiz)
856 {
857         if (!_backend) {
858                 return -1;
859         }
860         return _backend->set_buffer_size  (bufsiz);
861 }
862
863 int
864 AudioEngine::set_sample_format (SampleFormat sf)
865 {
866         if (!_backend) {
867                 return -1;
868         }
869         return _backend->set_sample_format  (sf);
870 }
871
872 int
873 AudioEngine::set_interleaved (bool yn)
874 {
875         if (!_backend) {
876                 return -1;
877         }
878         return _backend->set_interleaved  (yn);
879 }
880
881 int
882 AudioEngine::set_input_channels (uint32_t ic)
883 {
884         if (!_backend) {
885                 return -1;
886         }
887         return _backend->set_input_channels  (ic);
888 }
889
890 int
891 AudioEngine::set_output_channels (uint32_t oc)
892 {
893         if (!_backend) {
894                 return -1;
895         }
896         return _backend->set_output_channels (oc);
897 }
898
899 int
900 AudioEngine::set_systemic_input_latency (uint32_t il)
901 {
902         if (!_backend) {
903                 return -1;
904         }
905         return _backend->set_systemic_input_latency  (il);
906 }
907
908 int
909 AudioEngine::set_systemic_output_latency (uint32_t ol)
910 {
911         if (!_backend) {
912                 return -1;
913         }
914         return _backend->set_systemic_output_latency  (ol);
915 }
916
917 /* END OF BACKEND PROXY API */
918
919 void
920 AudioEngine::thread_init_callback (void* arg)
921 {
922         /* make sure that anybody who needs to know about this thread
923            knows about it.
924         */
925
926         pthread_set_name (X_("audioengine"));
927
928         PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
929         PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
930
931         SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
932
933         MIDI::JackMIDIPort::set_process_thread (pthread_self());
934
935         if (arg) {
936                 AudioEngine* ae = static_cast<AudioEngine*> (arg);
937                 /* the special thread created/managed by the backend */
938                 ae->_main_thread = new ProcessThread;
939         }
940 }
941
942 /* XXXX
943 void
944 AudioEngine::timebase_callback (TransportState state, pframes_t nframes, jack_position_t pos, int new_position)
945 {
946         if (_session && _session->synced_to_jack()) {
947                 // _session->timebase_callback (state, nframes, pos, new_position);
948         }
949 }
950 */
951
952 int
953 AudioEngine::sync_callback (TransportState state, framepos_t position)
954 {
955         if (_session) {
956                 return _session->jack_sync_callback (state, position);
957         }
958         return 0;
959 }
960
961 void
962 AudioEngine::freewheel_callback (bool onoff)
963 {
964         if (onoff) {
965                 _pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
966                 MIDI::Manager::instance()->mmc()->enable_send (false);
967         } else {
968                 MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled);
969         }
970 }
971
972 void
973 AudioEngine::latency_callback (bool for_playback)
974 {
975         if (_session) {
976                 _session->update_latency (for_playback);
977         }
978 }
979
980 void
981 AudioEngine::update_latencies ()
982 {
983         if (_backend) {
984                 _backend->update_latencies ();
985         }
986 }
987
988 void
989 AudioEngine::halted_callback (const char* why)
990 {
991         stop_metering_thread ();
992         
993         MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */
994         Halted (why); /* EMIT SIGNAL */
995 }