audioengine branch can now load and run at least one test session.
[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 ()
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 {
79         g_atomic_int_set (&m_meter_exit, 0);
80         discover_backends ();
81 }
82
83 AudioEngine::~AudioEngine ()
84 {
85         drop_backend ();
86
87         config_connection.disconnect ();
88
89         {
90                 Glib::Threads::Mutex::Lock tm (_process_lock);
91                 session_removed.signal ();
92                 stop_metering_thread ();
93         }
94 }
95
96 AudioEngine*
97 AudioEngine::create ()
98 {
99         if (_instance) {
100                 return _instance;
101         }
102
103         _instance = new AudioEngine ();
104         
105         return _instance;
106 }
107
108 void
109 _thread_init_callback (void * /*arg*/)
110 {
111         /* make sure that anybody who needs to know about this thread
112            knows about it.
113         */
114
115         pthread_set_name (X_("audioengine"));
116
117         PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("Audioengine"), 4096);
118         PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("Audioengine"), 128);
119
120         SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
121
122         MIDI::JackMIDIPort::set_process_thread (pthread_self());
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("*backend.so");
492         Glib::PatternSpec dylib_extension_pattern("*backend.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\n"), 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 (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                 return 0;
525         }
526         
527         if (!module.get_symbol ("descriptor", sym)) {
528                 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor."), path) << endmsg;
529                 error << Glib::Module::get_last_error() << endmsg;
530                 return 0;
531         }
532
533         module.make_resident ();
534         
535         info = (AudioBackendInfo*) sym;
536         
537         return info;
538 }
539
540 vector<const AudioBackendInfo*>
541 AudioEngine::available_backends() const
542 {
543         vector<const AudioBackendInfo*> r;
544         
545         for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
546                 r.push_back (i->second);
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                 BackendRemoved(); /* EMIT SIGNAL */
569         }
570 }
571
572 int
573 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
574 {
575         BackendMap::iterator b = _backends.find (name);
576
577         if (b == _backends.end()) {
578                 return -1;
579         }
580
581         drop_backend ();
582
583         try {
584                 cerr << "Instantiate " << b->second->name << " with " << arg1 << " + " << arg2 << endl;
585
586                 if (b->second->instantiate (arg1, arg2)) {
587                         cerr << "i failed\n";
588                         throw failed_constructor ();
589                 }
590
591                 cerr << "bf\n";
592                 _backend = b->second->backend_factory (*this);
593                 cerr << "pf\n";
594                 _impl = b->second->portengine_factory (*this);
595                 cerr << "done\n";
596
597         } catch (exception& e) {
598                 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
599                 return -1;
600         }
601
602         BackendAvailable (); /* EMIT SIGNAL */
603
604         return 0;
605 }
606
607 /* BACKEND PROXY WRAPPERS */
608
609 int
610 AudioEngine::start ()
611 {
612         if (!_backend) {
613                 return -1;
614         }
615
616         if (!_running) {
617
618                 if (_session) {
619                         BootMessage (_("Connect session to engine"));
620                         _session->set_frame_rate (_backend->sample_rate());
621                 }
622
623                 _processed_frames = 0;
624                 last_monitor_check = 0;
625
626                 if (_backend->start() == 0) {
627                         _running = true;
628                         _has_run = true;
629                         last_monitor_check = 0;
630
631                         if (_session && _session->config.get_jack_time_master()) {
632                                 _backend->set_time_master (true);
633                         }
634
635                         Running(); /* EMIT SIGNAL */
636                 } else {
637                         /* should report error? */
638                 }
639         }
640                 
641         return _running ? 0 : -1;
642 }
643
644 int
645 AudioEngine::stop ()
646 {
647         if (!_backend) {
648                 return 0;
649         }
650
651         Glib::Threads::Mutex::Lock lm (_process_lock);
652
653         if (_backend->stop () == 0) {
654                 _running = false;
655                 stop_metering_thread ();
656
657                 Stopped (); /* EMIT SIGNAL */
658
659                 return 0;
660         }
661
662         return -1;
663 }
664
665 int
666 AudioEngine::pause ()
667 {
668         if (!_backend) {
669                 return 0;
670         }
671         
672         if (_backend->pause () == 0) {
673                 _running = false;
674                 Stopped(); /* EMIT SIGNAL */
675                 return 0;
676         }
677
678         return -1;
679 }
680
681 int
682 AudioEngine::freewheel (bool start_stop)
683 {
684         if (!_backend) {
685                 return -1;
686         }
687
688         /* _freewheeling will be set when first Freewheel signal occurs */
689
690         return _backend->freewheel (start_stop);
691 }
692
693 float
694 AudioEngine::get_cpu_load() const 
695 {
696         if (!_backend) {
697                 return 0.0;
698         }
699         return _backend->cpu_load ();
700 }
701
702 bool
703 AudioEngine::is_realtime() const 
704 {
705         if (!_backend) {
706                 return false;
707         }
708
709         return _backend->is_realtime();
710 }
711
712 bool
713 AudioEngine::connected() const 
714 {
715         if (!_backend) {
716                 return false;
717         }
718
719         return _backend->connected();
720 }
721
722 void
723 AudioEngine::transport_start ()
724 {
725         if (!_backend) {
726                 return;
727         }
728         return _backend->transport_start ();
729 }
730
731 void
732 AudioEngine::transport_stop ()
733 {
734         if (!_backend) {
735                 return;
736         }
737         return _backend->transport_stop ();
738 }
739
740 TransportState
741 AudioEngine::transport_state ()
742 {
743         if (!_backend) {
744                 return TransportStopped;
745         }
746         return _backend->transport_state ();
747 }
748
749 void
750 AudioEngine::transport_locate (framepos_t pos)
751 {
752         if (!_backend) {
753                 return;
754         }
755         return _backend->transport_locate (pos);
756 }
757
758 framepos_t
759 AudioEngine::transport_frame()
760 {
761         if (!_backend) {
762                 return 0;
763         }
764         return _backend->transport_frame ();
765 }
766
767 framecnt_t
768 AudioEngine::sample_rate () const
769 {
770         if (!_backend) {
771                 return 0;
772         }
773         return _backend->sample_rate ();
774 }
775
776 pframes_t
777 AudioEngine::samples_per_cycle () const
778 {
779         if (!_backend) {
780                 return 0;
781         }
782         return _backend->buffer_size ();
783 }
784
785 int
786 AudioEngine::usecs_per_cycle () const
787 {
788         if (!_backend) {
789                 return -1;
790         }
791         return _backend->usecs_per_cycle ();
792 }
793
794 size_t
795 AudioEngine::raw_buffer_size (DataType t)
796 {
797         if (!_backend) {
798                 return -1;
799         }
800         return _backend->raw_buffer_size (t);
801 }
802
803 pframes_t
804 AudioEngine::sample_time ()
805 {
806         if (!_backend) {
807                 return 0;
808         }
809         return _backend->sample_time ();
810 }
811
812 pframes_t
813 AudioEngine::sample_time_at_cycle_start ()
814 {
815         if (!_backend) {
816                 return 0;
817         }
818         return _backend->sample_time_at_cycle_start ();
819 }
820
821 pframes_t
822 AudioEngine::samples_since_cycle_start ()
823 {
824         if (!_backend) {
825                 return 0;
826         }
827         return _backend->samples_since_cycle_start ();
828 }
829
830 bool
831 AudioEngine::get_sync_offset (pframes_t& offset) const
832 {
833         if (!_backend) {
834                 return false;
835         }
836         return _backend->get_sync_offset (offset);
837 }
838
839 int
840 AudioEngine::create_process_thread (boost::function<void()> func, pthread_t* thr, size_t stacksize)
841 {
842         if (!_backend) {
843                 return -1;
844         }
845         return _backend->create_process_thread (func, thr, stacksize);
846 }
847
848
849 int
850 AudioEngine::set_device_name (const std::string& name)
851 {
852         if (!_backend) {
853                 return -1;
854         }
855         return _backend->set_device_name  (name);
856 }
857
858 int
859 AudioEngine::set_sample_rate (float sr)
860 {
861         if (!_backend) {
862                 return -1;
863         }
864         return _backend->set_sample_rate  (sr);
865 }
866
867 int
868 AudioEngine::set_buffer_size (uint32_t bufsiz)
869 {
870         if (!_backend) {
871                 return -1;
872         }
873         return _backend->set_buffer_size  (bufsiz);
874 }
875
876 int
877 AudioEngine::set_sample_format (SampleFormat sf)
878 {
879         if (!_backend) {
880                 return -1;
881         }
882         return _backend->set_sample_format  (sf);
883 }
884
885 int
886 AudioEngine::set_interleaved (bool yn)
887 {
888         if (!_backend) {
889                 return -1;
890         }
891         return _backend->set_interleaved  (yn);
892 }
893
894 int
895 AudioEngine::set_input_channels (uint32_t ic)
896 {
897         if (!_backend) {
898                 return -1;
899         }
900         return _backend->set_input_channels  (ic);
901 }
902
903 int
904 AudioEngine::set_output_channels (uint32_t oc)
905 {
906         if (!_backend) {
907                 return -1;
908         }
909         return _backend->set_output_channels (oc);
910 }
911
912 int
913 AudioEngine::set_systemic_input_latency (uint32_t il)
914 {
915         if (!_backend) {
916                 return -1;
917         }
918         return _backend->set_systemic_input_latency  (il);
919 }
920
921 int
922 AudioEngine::set_systemic_output_latency (uint32_t ol)
923 {
924         if (!_backend) {
925                 return -1;
926         }
927         return _backend->set_systemic_output_latency  (ol);
928 }
929
930 /* END OF BACKEND PROXY API */
931
932 void
933 AudioEngine::thread_init_callback (void* arg)
934 {
935         /* make sure that anybody who needs to know about this thread
936            knows about it.
937         */
938
939         pthread_set_name (X_("audioengine"));
940
941         PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
942         PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
943
944         SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
945
946         MIDI::JackMIDIPort::set_process_thread (pthread_self());
947
948         if (arg) {
949                 AudioEngine* ae = static_cast<AudioEngine*> (arg);
950                 /* the special thread created/managed by the backend */
951                 ae->_main_thread = new ProcessThread;
952         }
953 }
954
955 /* XXXX
956 void
957 AudioEngine::timebase_callback (TransportState state, pframes_t nframes, jack_position_t pos, int new_position)
958 {
959         if (_session && _session->synced_to_jack()) {
960                 // _session->timebase_callback (state, nframes, pos, new_position);
961         }
962 }
963 */
964
965 int
966 AudioEngine::sync_callback (TransportState state, framepos_t position)
967 {
968         if (_session) {
969                 return _session->jack_sync_callback (state, position);
970         }
971         return 0;
972 }
973
974 void
975 AudioEngine::freewheel_callback (bool onoff)
976 {
977         if (onoff) {
978                 _pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
979                 MIDI::Manager::instance()->mmc()->enable_send (false);
980         } else {
981                 MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled);
982         }
983 }
984
985 void
986 AudioEngine::latency_callback (bool for_playback)
987 {
988         if (_session) {
989                 _session->update_latency (for_playback);
990         }
991 }
992
993 void
994 AudioEngine::update_latencies ()
995 {
996         if (_backend) {
997                 _backend->update_latencies ();
998         }
999 }
1000
1001 void
1002 AudioEngine::halted_callback (const char* why)
1003 {
1004         stop_metering_thread ();
1005         
1006         MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */
1007         Halted (why); /* EMIT SIGNAL */
1008 }
1009