use AudioEngine destructor to do necessary stuff when shutting it down, and remove...
[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++/mmc.h"
41
42 #include "ardour/async_midi_port.h"
43 #include "ardour/audio_port.h"
44 #include "ardour/audio_backend.h"
45 #include "ardour/audioengine.h"
46 #include "ardour/backend_search_path.h"
47 #include "ardour/buffer.h"
48 #include "ardour/cycle_timer.h"
49 #include "ardour/internal_send.h"
50 #include "ardour/meter.h"
51 #include "ardour/midi_port.h"
52 #include "ardour/midiport_manager.h"
53 #include "ardour/mtdm.h"
54 #include "ardour/port.h"
55 #include "ardour/process_thread.h"
56 #include "ardour/session.h"
57
58 #include "i18n.h"
59
60 using namespace std;
61 using namespace ARDOUR;
62 using namespace PBD;
63
64 gint AudioEngine::m_meter_exit;
65 AudioEngine* AudioEngine::_instance = 0;
66
67 AudioEngine::AudioEngine ()
68         : session_remove_pending (false)
69         , session_removal_countdown (-1)
70         , _running (false)
71         , _freewheeling (false)
72         , monitor_check_interval (INT32_MAX)
73         , last_monitor_check (0)
74         , _processed_frames (0)
75         , m_meter_thread (0)
76         , _main_thread (0)
77         , _mtdm (0)
78         , _measuring_latency (false)
79         , _latency_input_port (0)
80         , _latency_output_port (0)
81         , _latency_flush_frames (0)
82         , _latency_signal_latency (0)
83         , _started_for_latency (false)
84         , _in_destructor (false)
85 {
86         g_atomic_int_set (&m_meter_exit, 0);
87         discover_backends ();
88 }
89
90 AudioEngine::~AudioEngine ()
91 {
92         _in_destructor = true;
93         stop_metering_thread ();
94         drop_backend ();
95 }
96
97 AudioEngine*
98 AudioEngine::create ()
99 {
100         if (_instance) {
101                 return _instance;
102         }
103
104         _instance = new AudioEngine ();
105         
106         return _instance;
107 }
108
109 void
110 _thread_init_callback (void * /*arg*/)
111 {
112         /* make sure that anybody who needs to know about this thread
113            knows about it.
114         */
115
116         pthread_set_name (X_("audioengine"));
117
118         PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("Audioengine"), 4096);
119         PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("Audioengine"), 128);
120
121         SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
122
123         AsyncMIDIPort::set_process_thread (pthread_self());
124 }
125
126 void
127 AudioEngine::split_cycle (pframes_t offset)
128 {
129         /* caller must hold process lock */
130
131         Port::increment_global_port_buffer_offset (offset);
132
133         /* tell all Ports that we're going to start a new (split) cycle */
134
135         boost::shared_ptr<Ports> p = ports.reader();
136
137         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
138                 i->second->cycle_split ();
139         }
140 }
141
142 int
143 AudioEngine::sample_rate_change (pframes_t nframes)
144 {
145         /* check for monitor input change every 1/10th of second */
146
147         monitor_check_interval = nframes / 10;
148         last_monitor_check = 0;
149
150         if (_session) {
151                 _session->set_frame_rate (nframes);
152         }
153
154         SampleRateChanged (nframes); /* EMIT SIGNAL */
155
156         return 0;
157 }
158
159 int 
160 AudioEngine::buffer_size_change (pframes_t bufsiz)
161 {
162         if (_session) {
163                 _session->set_block_size (bufsiz);
164                 last_monitor_check = 0;
165         }
166
167         return 0;
168 }
169
170 /** Method called by our ::process_thread when there is work to be done.
171  *  @param nframes Number of frames to process.
172  */
173 int
174 AudioEngine::process_callback (pframes_t nframes)
175 {
176         Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
177
178         PT_TIMING_REF;
179         PT_TIMING_CHECK (1);
180
181         /// The number of frames that will have been processed when we've finished
182         pframes_t next_processed_frames;
183
184         /* handle wrap around of total frames counter */
185
186         if (max_framepos - _processed_frames < nframes) {
187                 next_processed_frames = nframes - (max_framepos - _processed_frames);
188         } else {
189                 next_processed_frames = _processed_frames + nframes;
190         }
191
192         if (!tm.locked()) {
193                 /* return having done nothing */
194                 _processed_frames = next_processed_frames;
195                 return 0;
196         }
197
198         bool return_after_remove_check = false;
199
200         if (_measuring_latency && _mtdm) {
201                 /* run a normal cycle from the perspective of the PortManager
202                    so that we get silence on all registered ports.
203                    
204                    we overwrite the silence on the two ports used for latency
205                    measurement.
206                 */
207                 
208                 PortManager::cycle_start (nframes);
209                 PortManager::silence (nframes);
210
211                 if (_latency_input_port && _latency_output_port) {
212                         PortEngine& pe (port_engine());
213
214                         Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
215                         Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
216
217                         _mtdm->process (nframes, in, out);
218                 }
219
220                 PortManager::cycle_end (nframes);
221                 return_after_remove_check = true;
222
223         } else if (_latency_flush_frames) {
224                 
225                 /* wait for the appropriate duration for the MTDM signal to
226                  * drain from the ports before we revert to normal behaviour.
227                  */
228
229                 PortManager::cycle_start (nframes);
230                 PortManager::silence (nframes);
231                 PortManager::cycle_end (nframes);
232                 
233                 if (_latency_flush_frames > nframes) {
234                         _latency_flush_frames -= nframes;
235                 } else {
236                         _latency_flush_frames = 0;
237                 }
238
239                 return_after_remove_check = true;
240         }
241
242         if (session_remove_pending) {
243
244                 /* perform the actual session removal */
245
246                 if (session_removal_countdown < 0) {
247
248                         /* fade out over 1 second */
249                         session_removal_countdown = sample_rate()/2;
250                         session_removal_gain = 1.0;
251                         session_removal_gain_step = 1.0/session_removal_countdown;
252
253                 } else if (session_removal_countdown > 0) {
254
255                         /* we'll be fading audio out.
256                            
257                            if this is the last time we do this as part 
258                            of session removal, do a MIDI panic now
259                            to get MIDI stopped. This relies on the fact
260                            that "immediate data" (aka "out of band data") from
261                            MIDI tracks is *appended* after any other data, 
262                            so that it emerges after any outbound note ons, etc.
263                         */
264
265                         if (session_removal_countdown <= nframes) {
266                                 _session->midi_panic ();
267                         }
268
269                 } else {
270                         /* fade out done */
271                         _session = 0;
272                         session_removal_countdown = -1; // reset to "not in progress"
273                         session_remove_pending = false;
274                         session_removed.signal(); // wakes up thread that initiated session removal
275                 }
276         }
277
278         if (return_after_remove_check) {
279                 return 0;
280         }
281
282         if (_session == 0) {
283
284                 if (!_freewheeling) {
285                         PortManager::cycle_start (nframes);
286                         PortManager::cycle_end (nframes);
287                 }
288
289                 _processed_frames = next_processed_frames;
290
291                 return 0;
292         }
293
294         /* tell all relevant objects that we're starting a new cycle */
295
296         InternalSend::CycleStart (nframes);
297
298         /* tell all Ports that we're starting a new cycle */
299
300         PortManager::cycle_start (nframes);
301
302         /* test if we are freewheeling and there are freewheel signals connected.
303            ardour should act normally even when freewheeling unless /it/ is
304            exporting (which is what Freewheel.empty() tests for).
305         */
306
307         if (_freewheeling && !Freewheel.empty()) {
308                 Freewheel (nframes);
309         } else {
310                 if (_session) {
311                         _session->process (nframes);
312                 }
313         }
314
315         if (_freewheeling) {
316                 return 0;
317         }
318
319         if (!_running) {
320                 _processed_frames = next_processed_frames;
321                 return 0;
322         }
323
324         if (last_monitor_check + monitor_check_interval < next_processed_frames) {
325                 
326                 PortManager::check_monitoring ();
327                 last_monitor_check = next_processed_frames;
328         }
329
330         if (_session->silent()) {
331                 PortManager::silence (nframes);
332         }
333
334         if (session_remove_pending && session_removal_countdown) {
335
336                 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
337                 
338                 if (session_removal_countdown > nframes) {
339                         session_removal_countdown -= nframes;
340                 } else {
341                         session_removal_countdown = 0;
342                 }
343
344                 session_removal_gain -= (nframes * session_removal_gain_step);
345         }
346
347         PortManager::cycle_end (nframes);
348
349         _processed_frames = next_processed_frames;
350
351         PT_TIMING_CHECK (2);
352         
353         return 0;
354 }
355
356
357 void
358 AudioEngine::stop_metering_thread ()
359 {
360         if (m_meter_thread) {
361                 g_atomic_int_set (&m_meter_exit, 1);
362                 m_meter_thread->join ();
363                 m_meter_thread = 0;
364         }
365 }
366
367 void
368 AudioEngine::start_metering_thread ()
369 {
370         if (m_meter_thread == 0) {
371                 g_atomic_int_set (&m_meter_exit, 0);
372                 m_meter_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::meter_thread, this));
373         }
374 }
375
376 void
377 AudioEngine::meter_thread ()
378 {
379         pthread_set_name (X_("meter"));
380
381         while (true) {
382                 Glib::usleep (10000); /* 1/100th sec interval */
383                 if (g_atomic_int_get(&m_meter_exit)) {
384                         break;
385                 }
386                 Metering::Meter ();
387         }
388 }
389
390 void
391 AudioEngine::set_session (Session *s)
392 {
393         Glib::Threads::Mutex::Lock pl (_process_lock);
394
395         SessionHandlePtr::set_session (s);
396
397         if (_session) {
398
399                 pframes_t blocksize = samples_per_cycle ();
400
401                 PortManager::cycle_start (blocksize);
402
403                 _session->process (blocksize);
404                 _session->process (blocksize);
405                 _session->process (blocksize);
406                 _session->process (blocksize);
407                 _session->process (blocksize);
408                 _session->process (blocksize);
409                 _session->process (blocksize);
410                 _session->process (blocksize);
411
412                 PortManager::cycle_end (blocksize);
413         }
414 }
415
416 void
417 AudioEngine::remove_session ()
418 {
419         Glib::Threads::Mutex::Lock lm (_process_lock);
420
421         if (_running) {
422
423                 if (_session) {
424                         session_remove_pending = true;
425                         session_removal_countdown = 0;
426                         session_removed.wait(_process_lock);
427                 }
428
429         } else {
430                 SessionHandlePtr::set_session (0);
431         }
432
433         remove_all_ports ();
434 }
435
436
437 void
438 AudioEngine::died ()
439 {
440         /* called from a signal handler for SIGPIPE */
441
442         stop_metering_thread ();
443
444         _running = false;
445 }
446
447 int
448 AudioEngine::reset_timebase ()
449 {
450         if (_session) {
451                 if (_session->config.get_jack_time_master()) {
452                         _backend->set_time_master (true);
453                 } else {
454                         _backend->set_time_master (false);
455                 }
456         }
457         return 0;
458 }
459
460
461 void
462 AudioEngine::destroy ()
463 {
464         delete _instance;
465         _instance = 0;
466 }
467
468 int
469 AudioEngine::discover_backends ()
470 {
471         vector<std::string> backend_modules;
472
473         _backends.clear ();
474
475         Glib::PatternSpec so_extension_pattern("*backend.so");
476         Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
477
478         find_matching_files_in_search_path (backend_search_path (),
479                                             so_extension_pattern, backend_modules);
480
481         find_matching_files_in_search_path (backend_search_path (),
482                                             dylib_extension_pattern, backend_modules);
483
484         DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1\n"), backend_search_path().to_string()));
485
486         for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
487
488                 AudioBackendInfo* info;
489
490                 if ((info = backend_discover (*i)) != 0) {
491                         _backends.insert (make_pair (info->name, info));
492                 }
493         }
494
495         return _backends.size();
496 }
497
498 AudioBackendInfo*
499 AudioEngine::backend_discover (const string& path)
500 {
501         Glib::Module module (path);
502         AudioBackendInfo* info;
503         AudioBackendInfo* (*dfunc)(void);
504         void* func = 0;
505
506         if (!module) {
507                 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
508                                         Glib::Module::get_last_error()) << endmsg;
509                 return 0;
510         }
511         
512         if (!module.get_symbol ("descriptor", func)) {
513                 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
514                 error << Glib::Module::get_last_error() << endmsg;
515                 return 0;
516         }
517
518         module.make_resident ();
519         
520         dfunc = (AudioBackendInfo* (*)(void))func;
521         info = dfunc();
522         
523         return info;
524 }
525
526 vector<const AudioBackendInfo*>
527 AudioEngine::available_backends() const
528 {
529         vector<const AudioBackendInfo*> r;
530         
531         for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
532                 r.push_back (i->second);
533         }
534
535         return r;
536 }
537
538 string
539 AudioEngine::current_backend_name() const
540 {
541         if (_backend) {
542                 return _backend->name();
543         } 
544         return string();
545 }
546
547 void
548 AudioEngine::drop_backend ()
549 {
550         if (_backend) {
551                 _backend->stop ();
552                 _backend.reset ();
553         }
554 }
555
556 boost::shared_ptr<AudioBackend>
557 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
558 {
559         BackendMap::iterator b = _backends.find (name);
560
561         if (b == _backends.end()) {
562                 return boost::shared_ptr<AudioBackend>();
563         }
564
565         drop_backend ();
566         
567         try {
568                 if (b->second->instantiate (arg1, arg2)) {
569                         throw failed_constructor ();
570                 }
571
572                 _backend = b->second->factory (*this);
573
574         } catch (exception& e) {
575                 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
576                 return boost::shared_ptr<AudioBackend>();
577         }
578
579         return _backend;
580 }
581
582 /* BACKEND PROXY WRAPPERS */
583
584 int
585 AudioEngine::start ()
586 {
587         if (!_backend) {
588                 return -1;
589         }
590
591         if (_running) {
592                 return 0;
593         }
594
595         _processed_frames = 0;
596         last_monitor_check = 0;
597         
598         if (_backend->start()) {
599                 return -1;
600         }
601
602         _running = true;
603         
604         if (_session) {
605                 _session->set_frame_rate (_backend->sample_rate());
606                 
607                 if (_session->config.get_jack_time_master()) {
608                         _backend->set_time_master (true);
609                 }
610         }
611         
612         start_metering_thread ();
613         
614         if (!_started_for_latency) {
615                 Running(); /* EMIT SIGNAL */
616         }
617         
618         return 0;
619 }
620
621 int
622 AudioEngine::stop ()
623 {
624         if (!_backend) {
625                 return 0;
626         }
627
628         Glib::Threads::Mutex::Lock lm (_process_lock);
629
630         if (_backend->stop ()) {
631                 return -1;
632         }
633         
634         _running = false;
635         _processed_frames = 0;
636         _measuring_latency = false;
637         _latency_output_port = 0;
638         _latency_input_port = 0;
639         _started_for_latency = false;
640         stop_metering_thread ();
641         
642         Port::PortDrop ();
643         Stopped (); /* EMIT SIGNAL */
644         
645         return 0;
646 }
647
648 int
649 AudioEngine::pause ()
650 {
651         if (!_backend) {
652                 return 0;
653         }
654         
655         if (_backend->pause ()) {
656                 return -1;
657         }
658
659         _running = false;
660         
661         Stopped(); /* EMIT SIGNAL */
662         return 0;
663 }
664
665 int
666 AudioEngine::freewheel (bool start_stop)
667 {
668         if (!_backend) {
669                 return -1;
670         }
671
672         /* _freewheeling will be set when first Freewheel signal occurs */
673
674         return _backend->freewheel (start_stop);
675 }
676
677 float
678 AudioEngine::get_cpu_load() const 
679 {
680         if (!_backend) {
681                 return 0.0;
682         }
683         return _backend->cpu_load ();
684 }
685
686 bool
687 AudioEngine::is_realtime() const 
688 {
689         if (!_backend) {
690                 return false;
691         }
692
693         return _backend->is_realtime();
694 }
695
696 bool
697 AudioEngine::connected() const 
698 {
699         if (!_backend) {
700                 return false;
701         }
702
703         return _backend->available();
704 }
705
706 void
707 AudioEngine::transport_start ()
708 {
709         if (!_backend) {
710                 return;
711         }
712         return _backend->transport_start ();
713 }
714
715 void
716 AudioEngine::transport_stop ()
717 {
718         if (!_backend) {
719                 return;
720         }
721         return _backend->transport_stop ();
722 }
723
724 TransportState
725 AudioEngine::transport_state ()
726 {
727         if (!_backend) {
728                 return TransportStopped;
729         }
730         return _backend->transport_state ();
731 }
732
733 void
734 AudioEngine::transport_locate (framepos_t pos)
735 {
736         if (!_backend) {
737                 return;
738         }
739         return _backend->transport_locate (pos);
740 }
741
742 framepos_t
743 AudioEngine::transport_frame()
744 {
745         if (!_backend) {
746                 return 0;
747         }
748         return _backend->transport_frame ();
749 }
750
751 framecnt_t
752 AudioEngine::sample_rate () const
753 {
754         if (!_backend) {
755                 return 0;
756         }
757         return _backend->sample_rate ();
758 }
759
760 pframes_t
761 AudioEngine::samples_per_cycle () const
762 {
763         if (!_backend) {
764                 return 0;
765         }
766         return _backend->buffer_size ();
767 }
768
769 int
770 AudioEngine::usecs_per_cycle () const
771 {
772         if (!_backend) {
773                 return -1;
774         }
775         return _backend->usecs_per_cycle ();
776 }
777
778 size_t
779 AudioEngine::raw_buffer_size (DataType t)
780 {
781         if (!_backend) {
782                 return -1;
783         }
784         return _backend->raw_buffer_size (t);
785 }
786
787 pframes_t
788 AudioEngine::sample_time ()
789 {
790         if (!_backend) {
791                 return 0;
792         }
793         return _backend->sample_time ();
794 }
795
796 pframes_t
797 AudioEngine::sample_time_at_cycle_start ()
798 {
799         if (!_backend) {
800                 return 0;
801         }
802         return _backend->sample_time_at_cycle_start ();
803 }
804
805 pframes_t
806 AudioEngine::samples_since_cycle_start ()
807 {
808         if (!_backend) {
809                 return 0;
810         }
811         return _backend->samples_since_cycle_start ();
812 }
813
814 bool
815 AudioEngine::get_sync_offset (pframes_t& offset) const
816 {
817         if (!_backend) {
818                 return false;
819         }
820         return _backend->get_sync_offset (offset);
821 }
822
823 int
824 AudioEngine::create_process_thread (boost::function<void()> func)
825 {
826         if (!_backend) {
827                 return -1;
828         }
829         return _backend->create_process_thread (func);
830 }
831
832 int
833 AudioEngine::join_process_threads ()
834 {
835         if (!_backend) {
836                 return -1;
837         }
838         return _backend->join_process_threads ();
839 }
840
841 bool
842 AudioEngine::in_process_thread ()
843 {
844         if (!_backend) {
845                 return false;
846         }
847         return _backend->in_process_thread ();
848 }
849
850 uint32_t
851 AudioEngine::process_thread_count ()
852 {
853         if (!_backend) {
854                 return 0;
855         }
856         return _backend->process_thread_count ();
857 }
858
859 int
860 AudioEngine::set_device_name (const std::string& name)
861 {
862         if (!_backend) {
863                 return -1;
864         }
865         return _backend->set_device_name  (name);
866 }
867
868 int
869 AudioEngine::set_sample_rate (float sr)
870 {
871         if (!_backend) {
872                 return -1;
873         }
874         return _backend->set_sample_rate  (sr);
875 }
876
877 int
878 AudioEngine::set_buffer_size (uint32_t bufsiz)
879 {
880         if (!_backend) {
881                 return -1;
882         }
883         return _backend->set_buffer_size  (bufsiz);
884 }
885
886 int
887 AudioEngine::set_sample_format (SampleFormat sf)
888 {
889         if (!_backend) {
890                 return -1;
891         }
892         return _backend->set_sample_format  (sf);
893 }
894
895 int
896 AudioEngine::set_interleaved (bool yn)
897 {
898         if (!_backend) {
899                 return -1;
900         }
901         return _backend->set_interleaved  (yn);
902 }
903
904 int
905 AudioEngine::set_input_channels (uint32_t ic)
906 {
907         if (!_backend) {
908                 return -1;
909         }
910         return _backend->set_input_channels  (ic);
911 }
912
913 int
914 AudioEngine::set_output_channels (uint32_t oc)
915 {
916         if (!_backend) {
917                 return -1;
918         }
919         return _backend->set_output_channels (oc);
920 }
921
922 int
923 AudioEngine::set_systemic_input_latency (uint32_t il)
924 {
925         if (!_backend) {
926                 return -1;
927         }
928         return _backend->set_systemic_input_latency  (il);
929 }
930
931 int
932 AudioEngine::set_systemic_output_latency (uint32_t ol)
933 {
934         if (!_backend) {
935                 return -1;
936         }
937         return _backend->set_systemic_output_latency  (ol);
938 }
939
940 /* END OF BACKEND PROXY API */
941
942 void
943 AudioEngine::thread_init_callback (void* arg)
944 {
945         /* make sure that anybody who needs to know about this thread
946            knows about it.
947         */
948
949         pthread_set_name (X_("audioengine"));
950
951         PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
952         PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
953
954         SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
955
956         AsyncMIDIPort::set_process_thread (pthread_self());
957
958         if (arg) {
959                 /* the special thread created/managed by the backend */
960                 AudioEngine::instance()->_main_thread = new ProcessThread;
961         }
962 }
963
964 int
965 AudioEngine::sync_callback (TransportState state, framepos_t position)
966 {
967         if (_session) {
968                 return _session->backend_sync_callback (state, position);
969         }
970         return 0;
971 }
972
973 void
974 AudioEngine::freewheel_callback (bool onoff)
975 {
976         _freewheeling = onoff;
977 }
978
979 void
980 AudioEngine::latency_callback (bool for_playback)
981 {
982         if (_session) {
983                 _session->update_latency (for_playback);
984         }
985 }
986
987 void
988 AudioEngine::update_latencies ()
989 {
990         if (_backend) {
991                 _backend->update_latencies ();
992         }
993 }
994
995 void
996 AudioEngine::halted_callback (const char* why)
997 {
998         if (_in_destructor) {
999                 /* everything is under control */
1000                 return;
1001         }
1002
1003         stop_metering_thread ();
1004         _running = false;
1005
1006         Port::PortDrop (); /* EMIT SIGNAL */
1007         Halted (why);      /* EMIT SIGNAL */
1008 }
1009
1010 bool
1011 AudioEngine::setup_required () const
1012 {
1013         /* If there is only a single backend and it claims to be configured
1014          * already there is no setup to be done.
1015          *
1016          * Primarily for a case where there is only a JACK backend and
1017          * JACK is already running.
1018          */
1019          
1020         if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1021                 return false;
1022         }
1023
1024         return true;
1025 }
1026
1027 MTDM*
1028 AudioEngine::mtdm() 
1029 {
1030         return _mtdm;
1031 }
1032
1033 int
1034 AudioEngine::prepare_for_latency_measurement ()
1035 {
1036         if (!running()) {
1037                 _started_for_latency = true;
1038
1039                 if (start()) {
1040                         _started_for_latency = false;
1041                         return -1;
1042                 }
1043         }
1044
1045         return 0;
1046 }
1047
1048 void
1049 AudioEngine::start_latency_detection ()
1050 {
1051         if (prepare_for_latency_measurement ()) {
1052                 return;
1053         }
1054
1055         PortEngine& pe (port_engine());
1056
1057         delete _mtdm;
1058         _mtdm = 0;
1059
1060         /* find the ports we will connect to */
1061
1062         PortEngine::PortHandle* out = pe.get_port_by_name (_latency_output_name);
1063         PortEngine::PortHandle* in = pe.get_port_by_name (_latency_input_name);
1064
1065         if (!out || !in) {
1066                 return;
1067         }
1068
1069         /* create the ports we will use to read/write data */
1070         
1071         if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1072                 return;
1073         }
1074         if (pe.connect (_latency_output_port, _latency_output_name)) {
1075                 pe.unregister_port (_latency_output_port);
1076                 return;
1077         }
1078
1079         const string portname ("latency_in");
1080         if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1081                 pe.unregister_port (_latency_output_port);
1082                 return;
1083         }
1084         if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1085                 pe.unregister_port (_latency_output_port);
1086                 return;
1087         }
1088
1089         LatencyRange lr;
1090         _latency_signal_latency = 0;
1091         lr = pe.get_latency_range (in, false);
1092         _latency_signal_latency = lr.max;
1093         lr = pe.get_latency_range (out, true);
1094         _latency_signal_latency += lr.max;
1095
1096         /* all created and connected, lets go */
1097
1098         _mtdm = new MTDM (sample_rate());
1099         _measuring_latency = true;
1100         _latency_flush_frames = samples_per_cycle();
1101
1102 }
1103
1104 void
1105 AudioEngine::stop_latency_detection ()
1106 {
1107         _measuring_latency = false;
1108
1109         if (_latency_output_port) {
1110                 port_engine().unregister_port (_latency_output_port);
1111                 _latency_output_port = 0;
1112         }
1113         if (_latency_input_port) {
1114                 port_engine().unregister_port (_latency_input_port);
1115                 _latency_input_port = 0;
1116         }
1117         if (_started_for_latency) {
1118                 stop ();
1119         }
1120 }
1121
1122 void
1123 AudioEngine::set_latency_output_port (const string& name)
1124 {
1125         _latency_output_name = name;
1126 }
1127
1128 void
1129 AudioEngine::set_latency_input_port (const string& name)
1130 {
1131         _latency_input_name = name;
1132 }