add copyright comments
[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
29 #include "pbd/pthread_utils.h"
30 #include "pbd/stacktrace.h"
31 #include "pbd/unknown_type.h"
32 #include "pbd/epa.h"
33
34 #include <jack/weakjack.h>
35
36 #include "midi++/port.h"
37 #include "midi++/jack_midi_port.h"
38 #include "midi++/mmc.h"
39 #include "midi++/manager.h"
40
41 #include "ardour/audio_port.h"
42 #include "ardour/audioengine.h"
43 #include "ardour/buffer.h"
44 #include "ardour/cycle_timer.h"
45 #include "ardour/internal_send.h"
46 #include "ardour/meter.h"
47 #include "ardour/midi_port.h"
48 #include "ardour/port.h"
49 #include "ardour/process_thread.h"
50 #include "ardour/session.h"
51
52 #include "i18n.h"
53
54 using namespace std;
55 using namespace ARDOUR;
56 using namespace PBD;
57
58 gint AudioEngine::m_meter_exit;
59 AudioEngine* AudioEngine::_instance = 0;
60
61 #define GET_PRIVATE_JACK_POINTER(j)  jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return; }
62 #define GET_PRIVATE_JACK_POINTER_RET(j,r) jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return r; }
63
64 AudioEngine::AudioEngine (string client_name, string session_uuid)
65         : _jack (0)
66         , session_remove_pending (false)
67         , session_removal_countdown (-1)
68         , _running (false)
69         , _has_run (false)
70         , _buffer_size (0)
71         , _frame_rate (0)
72         , monitor_check_interval (INT32_MAX)
73         , last_monitor_check (0)
74         , _processed_frames (0)
75         , _freewheeling (false)
76         , _pre_freewheel_mmc_enabled (false)
77         , _usecs_per_cycle (0)
78         , port_remove_in_progress (false)
79         , m_meter_thread (0)
80         , _main_thread (0)
81         , ports (new Ports)
82 {
83         _instance = this; /* singleton */
84
85         g_atomic_int_set (&m_meter_exit, 0);
86
87         if (connect_to_jack (client_name, session_uuid)) {
88                 throw NoBackendAvailable ();
89         }
90
91         Port::set_engine (this);
92 }
93
94 AudioEngine::~AudioEngine ()
95 {
96         config_connection.disconnect ();
97
98         {
99                 Glib::Threads::Mutex::Lock tm (_process_lock);
100                 session_removed.signal ();
101
102                 if (_running) {
103                         jack_client_close (_jack);
104                         _jack = 0;
105                 }
106
107                 stop_metering_thread ();
108         }
109 }
110
111 jack_client_t*
112 AudioEngine::jack() const
113 {
114         return _jack;
115 }
116
117 void
118 _thread_init_callback (void * /*arg*/)
119 {
120         /* make sure that anybody who needs to know about this thread
121            knows about it.
122         */
123
124         pthread_set_name (X_("audioengine"));
125
126         PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("Audioengine"), 4096);
127         PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("Audioengine"), 128);
128
129         SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
130
131         MIDI::JackMIDIPort::set_process_thread (pthread_self());
132 }
133
134 static void
135 ardour_jack_error (const char* msg)
136 {
137         error << "JACK: " << msg << endmsg;
138 }
139
140 void
141 AudioEngine::set_jack_callbacks ()
142 {
143         GET_PRIVATE_JACK_POINTER (_jack);
144
145         if (jack_on_info_shutdown) {
146                 jack_on_info_shutdown (_priv_jack, halted_info, this);
147         } else {
148                 jack_on_shutdown (_priv_jack, halted, this);
149         }
150
151         jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this);
152         jack_set_process_thread (_priv_jack, _process_thread, this);
153         jack_set_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
154         jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
155         jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this);
156         jack_set_port_registration_callback (_priv_jack, _registration_callback, this);
157         jack_set_port_connect_callback (_priv_jack, _connect_callback, this);
158         jack_set_xrun_callback (_priv_jack, _xrun_callback, this);
159         jack_set_sync_callback (_priv_jack, _jack_sync_callback, this);
160         jack_set_freewheel_callback (_priv_jack, _freewheel_callback, this);
161
162         if (_session && _session->config.get_jack_time_master()) {
163                 jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
164         }
165
166 #ifdef HAVE_JACK_SESSION
167         if( jack_set_session_callback)
168                 jack_set_session_callback (_priv_jack, _session_callback, this);
169 #endif
170
171         if (jack_set_latency_callback) {
172                 jack_set_latency_callback (_priv_jack, _latency_callback, this);
173         }
174
175         jack_set_error_function (ardour_jack_error);
176 }
177
178 int
179 AudioEngine::start ()
180 {
181         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
182
183         if (!_running) {
184
185                 if (!jack_port_type_get_buffer_size) {
186                         warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg;
187                 }
188
189                 if (_session) {
190                         BootMessage (_("Connect session to engine"));
191                         _session->set_frame_rate (jack_get_sample_rate (_priv_jack));
192                 }
193
194                 /* a proxy for whether jack_activate() will definitely call the buffer size
195                  * callback. with older versions of JACK, this function symbol will be null.
196                  * this is reliable, but not clean.
197                  */
198
199                 if (!jack_port_type_get_buffer_size) {
200                         jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
201                 }
202                 
203                 _processed_frames = 0;
204                 last_monitor_check = 0;
205
206                 set_jack_callbacks ();
207
208                 if (jack_activate (_priv_jack) == 0) {
209                         _running = true;
210                         _has_run = true;
211                         Running(); /* EMIT SIGNAL */
212                 } else {
213                         // error << _("cannot activate JACK client") << endmsg;
214                 }
215         }
216                 
217         return _running ? 0 : -1;
218 }
219
220 int
221 AudioEngine::stop (bool forever)
222 {
223         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
224
225         if (_priv_jack) {
226                 if (forever) {
227                         disconnect_from_jack ();
228                 } else {
229                         jack_deactivate (_priv_jack);
230                         MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
231                         Stopped(); /* EMIT SIGNAL */
232                 }
233         }
234
235         if (forever) {
236                 stop_metering_thread ();
237         }
238
239         return _running ? -1 : 0;
240 }
241
242
243 bool
244 AudioEngine::get_sync_offset (pframes_t& offset) const
245 {
246
247 #ifdef HAVE_JACK_VIDEO_SUPPORT
248
249         GET_PRIVATE_JACK_POINTER_RET (_jack, false);
250
251         jack_position_t pos;
252
253         if (_priv_jack) {
254                 (void) jack_transport_query (_priv_jack, &pos);
255
256                 if (pos.valid & JackVideoFrameOffset) {
257                         offset = pos.video_offset;
258                         return true;
259                 }
260         }
261 #else
262         /* keep gcc happy */
263         offset = 0;
264 #endif
265
266         return false;
267 }
268
269 void
270 AudioEngine::_jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
271                                       jack_position_t* pos, int new_position, void *arg)
272 {
273         static_cast<AudioEngine*> (arg)->jack_timebase_callback (state, nframes, pos, new_position);
274 }
275
276 void
277 AudioEngine::jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
278                                      jack_position_t* pos, int new_position)
279 {
280         if (_jack && _session && _session->synced_to_jack()) {
281                 _session->jack_timebase_callback (state, nframes, pos, new_position);
282         }
283 }
284
285 int
286 AudioEngine::_jack_sync_callback (jack_transport_state_t state, jack_position_t* pos, void* arg)
287 {
288         return static_cast<AudioEngine*> (arg)->jack_sync_callback (state, pos);
289 }
290
291 int
292 AudioEngine::jack_sync_callback (jack_transport_state_t state, jack_position_t* pos)
293 {
294         if (_jack && _session) {
295                 return _session->jack_sync_callback (state, pos);
296         }
297
298         return true;
299 }
300
301 int
302 AudioEngine::_xrun_callback (void *arg)
303 {
304         AudioEngine* ae = static_cast<AudioEngine*> (arg);
305         if (ae->connected()) {
306                 ae->Xrun (); /* EMIT SIGNAL */
307         }
308         return 0;
309 }
310
311 #ifdef HAVE_JACK_SESSION
312 void
313 AudioEngine::_session_callback (jack_session_event_t *event, void *arg)
314 {
315         AudioEngine* ae = static_cast<AudioEngine*> (arg);
316         if (ae->connected()) {
317                 ae->JackSessionEvent ( event ); /* EMIT SIGNAL */
318         }
319 }
320 #endif
321
322 int
323 AudioEngine::_graph_order_callback (void *arg)
324 {
325         AudioEngine* ae = static_cast<AudioEngine*> (arg);
326
327         if (ae->connected() && !ae->port_remove_in_progress) {
328                 ae->GraphReordered (); /* EMIT SIGNAL */
329         }
330         
331         return 0;
332 }
333
334 void*
335 AudioEngine::_process_thread (void *arg)
336 {
337         return static_cast<AudioEngine *> (arg)->process_thread ();
338 }
339
340 void
341 AudioEngine::_freewheel_callback (int onoff, void *arg)
342 {
343         static_cast<AudioEngine*>(arg)->freewheel_callback (onoff);
344 }
345
346 void
347 AudioEngine::freewheel_callback (int onoff)
348 {
349         _freewheeling = onoff;
350
351         if (onoff) {
352                 _pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
353                 MIDI::Manager::instance()->mmc()->enable_send (false);
354         } else {
355                 MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled);
356         }
357 }
358
359 void
360 AudioEngine::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg)
361 {
362         AudioEngine* ae = static_cast<AudioEngine*> (arg);
363
364         if (!ae->port_remove_in_progress) {
365                 ae->PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
366         }
367 }
368
369 void
370 AudioEngine::_latency_callback (jack_latency_callback_mode_t mode, void* arg)
371 {
372         return static_cast<AudioEngine *> (arg)->jack_latency_callback (mode);
373 }
374
375 void
376 AudioEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg)
377 {
378         AudioEngine* ae = static_cast<AudioEngine*> (arg);
379         ae->connect_callback (id_a, id_b, conn);
380 }
381
382 void
383 AudioEngine::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn)
384 {
385         if (port_remove_in_progress) {
386                 return;
387         }
388
389         GET_PRIVATE_JACK_POINTER (_jack);
390
391         jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a);
392         jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b);
393
394         boost::shared_ptr<Port> port_a;
395         boost::shared_ptr<Port> port_b;
396         Ports::iterator x;
397         boost::shared_ptr<Ports> pr = ports.reader ();
398
399
400         x = pr->find (make_port_name_relative (jack_port_name (jack_port_a)));
401         if (x != pr->end()) {
402                 port_a = x->second;
403         }
404
405         x = pr->find (make_port_name_relative (jack_port_name (jack_port_b)));
406         if (x != pr->end()) {
407                 port_b = x->second;
408         }
409
410         PortConnectedOrDisconnected (
411                 port_a, jack_port_name (jack_port_a),
412                 port_b, jack_port_name (jack_port_b),
413                 conn == 0 ? false : true
414                 ); /* EMIT SIGNAL */
415 }
416
417 void
418 AudioEngine::split_cycle (pframes_t offset)
419 {
420         /* caller must hold process lock */
421
422         Port::increment_global_port_buffer_offset (offset);
423
424         /* tell all Ports that we're going to start a new (split) cycle */
425
426         boost::shared_ptr<Ports> p = ports.reader();
427
428         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
429                 i->second->cycle_split ();
430         }
431 }
432
433 void*
434 AudioEngine::process_thread ()
435 {
436         /* JACK doesn't do this for us when we use the wait API
437          */
438
439         _thread_init_callback (0);
440
441         _main_thread = new ProcessThread;
442
443         while (1) {
444                 GET_PRIVATE_JACK_POINTER_RET(_jack,0);
445
446                 pframes_t nframes = jack_cycle_wait (_priv_jack);
447
448                 if (process_callback (nframes)) {
449                         return 0;
450                 }
451
452                 jack_cycle_signal (_priv_jack, 0);
453         }
454
455         return 0;
456 }
457
458 /** Method called by our ::process_thread when there is work to be done.
459  *  @param nframes Number of frames to process.
460  */
461 int
462 AudioEngine::process_callback (pframes_t nframes)
463 {
464         GET_PRIVATE_JACK_POINTER_RET(_jack,0);
465         Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
466
467         PT_TIMING_REF;
468         PT_TIMING_CHECK (1);
469
470         /// The number of frames that will have been processed when we've finished
471         pframes_t next_processed_frames;
472
473         /* handle wrap around of total frames counter */
474
475         if (max_framepos - _processed_frames < nframes) {
476                 next_processed_frames = nframes - (max_framepos - _processed_frames);
477         } else {
478                 next_processed_frames = _processed_frames + nframes;
479         }
480
481         if (!tm.locked()) {
482                 /* return having done nothing */
483                 _processed_frames = next_processed_frames;
484                 return 0;
485         }
486
487         if (session_remove_pending) {
488
489                 /* perform the actual session removal */
490
491                 if (session_removal_countdown < 0) {
492
493                         /* fade out over 1 second */
494                         session_removal_countdown = _frame_rate/2;
495                         session_removal_gain = 1.0;
496                         session_removal_gain_step = 1.0/session_removal_countdown;
497
498                 } else if (session_removal_countdown > 0) {
499
500                         /* we'll be fading audio out.
501                            
502                            if this is the last time we do this as part 
503                            of session removal, do a MIDI panic now
504                            to get MIDI stopped. This relies on the fact
505                            that "immediate data" (aka "out of band data") from
506                            MIDI tracks is *appended* after any other data, 
507                            so that it emerges after any outbound note ons, etc.
508                         */
509
510                         if (session_removal_countdown <= nframes) {
511                                 _session->midi_panic ();
512                         }
513
514                 } else {
515                         /* fade out done */
516                         _session = 0;
517                         session_removal_countdown = -1; // reset to "not in progress"
518                         session_remove_pending = false;
519                         session_removed.signal(); // wakes up thread that initiated session removal
520                 }
521         }
522
523         if (_session == 0) {
524
525                 if (!_freewheeling) {
526                         MIDI::Manager::instance()->cycle_start(nframes);
527                         MIDI::Manager::instance()->cycle_end();
528                 }
529
530                 _processed_frames = next_processed_frames;
531
532                 return 0;
533         }
534
535         /* tell all relevant objects that we're starting a new cycle */
536
537         InternalSend::CycleStart (nframes);
538         Port::set_global_port_buffer_offset (0);
539         Port::set_cycle_framecnt (nframes);
540
541         /* tell all Ports that we're starting a new cycle */
542
543         boost::shared_ptr<Ports> p = ports.reader();
544
545         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
546                 i->second->cycle_start (nframes);
547         }
548
549         /* test if we are freewheeling and there are freewheel signals connected.
550            ardour should act normally even when freewheeling unless /it/ is
551            exporting 
552         */
553
554         if (_freewheeling && !Freewheel.empty()) {
555
556                 Freewheel (nframes);
557
558         } else {
559                 MIDI::Manager::instance()->cycle_start(nframes);
560
561                 if (_session) {
562                         _session->process (nframes);
563                 }
564
565                 MIDI::Manager::instance()->cycle_end();
566         }
567
568         if (_freewheeling) {
569                 return 0;
570         }
571
572         if (!_running) {
573                 _processed_frames = next_processed_frames;
574                 return 0;
575         }
576
577         if (last_monitor_check + monitor_check_interval < next_processed_frames) {
578
579                 boost::shared_ptr<Ports> p = ports.reader();
580
581                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
582
583                         bool x;
584
585                         if (i->second->last_monitor() != (x = i->second->jack_monitoring_input ())) {
586                                 i->second->set_last_monitor (x);
587                                 /* XXX I think this is dangerous, due to
588                                    a likely mutex in the signal handlers ...
589                                 */
590                                 i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
591                         }
592                 }
593                 last_monitor_check = next_processed_frames;
594         }
595
596         if (_session->silent()) {
597
598                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
599
600                         if (i->second->sends_output()) {
601                                 i->second->get_buffer(nframes).silence(nframes);
602                         }
603                 }
604         }
605
606         if (session_remove_pending && session_removal_countdown) {
607
608                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
609
610                         if (i->second->sends_output()) {
611
612                                 boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
613                                 if (ap) {
614                                         Sample* s = ap->engine_get_whole_audio_buffer ();
615                                         gain_t g = session_removal_gain;
616                                         
617                                         for (pframes_t n = 0; n < nframes; ++n) {
618                                                 *s++ *= g;
619                                                 g -= session_removal_gain_step;
620                                         }
621                                 }
622                         }
623                 }
624                 
625                 if (session_removal_countdown > nframes) {
626                         session_removal_countdown -= nframes;
627                 } else {
628                         session_removal_countdown = 0;
629                 }
630
631                 session_removal_gain -= (nframes * session_removal_gain_step);
632         }
633
634         // Finalize ports
635
636         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
637                 i->second->cycle_end (nframes);
638         }
639
640         _processed_frames = next_processed_frames;
641
642         PT_TIMING_CHECK (2);
643         
644         return 0;
645 }
646
647 int
648 AudioEngine::_sample_rate_callback (pframes_t nframes, void *arg)
649 {
650         return static_cast<AudioEngine *> (arg)->jack_sample_rate_callback (nframes);
651 }
652
653 int
654 AudioEngine::jack_sample_rate_callback (pframes_t nframes)
655 {
656         _frame_rate = nframes;
657         _usecs_per_cycle = (int) floor ((((double) frames_per_cycle() / nframes)) * 1000000.0);
658
659         /* check for monitor input change every 1/10th of second */
660
661         monitor_check_interval = nframes / 10;
662         last_monitor_check = 0;
663
664         if (_session) {
665                 _session->set_frame_rate (nframes);
666         }
667
668         SampleRateChanged (nframes); /* EMIT SIGNAL */
669
670         return 0;
671 }
672
673 void
674 AudioEngine::jack_latency_callback (jack_latency_callback_mode_t mode)
675 {
676         if (_session) {
677                 _session->update_latency (mode == JackPlaybackLatency);
678         }
679 }
680
681 int
682 AudioEngine::_bufsize_callback (pframes_t nframes, void *arg)
683 {
684         return static_cast<AudioEngine *> (arg)->jack_bufsize_callback (nframes);
685 }
686
687 int
688 AudioEngine::jack_bufsize_callback (pframes_t nframes)
689 {
690         /* if the size has not changed, this should be a no-op */
691
692         if (nframes == _buffer_size) {
693                 return 0;
694         }
695
696         GET_PRIVATE_JACK_POINTER_RET (_jack, 1);
697
698         _buffer_size = nframes;
699         _usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0);
700         last_monitor_check = 0;
701
702         if (jack_port_type_get_buffer_size) {
703                 _raw_buffer_sizes[DataType::AUDIO] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_AUDIO_TYPE);
704                 _raw_buffer_sizes[DataType::MIDI] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_MIDI_TYPE);
705         } else {
706
707                 /* Old version of JACK.
708
709                    These crude guesses, see below where we try to get the right answers.
710
711                    Note that our guess for MIDI deliberatey tries to overestimate
712                    by a little. It would be nicer if we could get the actual
713                    size from a port, but we have to use this estimate in the
714                    event that there are no MIDI ports currently. If there are
715                    the value will be adjusted below.
716                 */
717
718                 _raw_buffer_sizes[DataType::AUDIO] = nframes * sizeof (Sample);
719                 _raw_buffer_sizes[DataType::MIDI] = nframes * 4 - (nframes/2);
720         }
721
722         {
723                 Glib::Threads::Mutex::Lock lm (_process_lock);
724
725                 boost::shared_ptr<Ports> p = ports.reader();
726
727                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
728                         i->second->reset();
729                 }
730         }
731
732         if (_session) {
733                 _session->set_block_size (_buffer_size);
734         }
735
736         return 0;
737 }
738
739 void
740 AudioEngine::stop_metering_thread ()
741 {
742         if (m_meter_thread) {
743                 g_atomic_int_set (&m_meter_exit, 1);
744                 m_meter_thread->join ();
745                 m_meter_thread = 0;
746         }
747 }
748
749 void
750 AudioEngine::start_metering_thread ()
751 {
752         if (m_meter_thread == 0) {
753                 g_atomic_int_set (&m_meter_exit, 0);
754                 m_meter_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::meter_thread, this));
755         }
756 }
757
758 void
759 AudioEngine::meter_thread ()
760 {
761         pthread_set_name (X_("meter"));
762
763         while (true) {
764                 Glib::usleep (10000); /* 1/100th sec interval */
765                 if (g_atomic_int_get(&m_meter_exit)) {
766                         break;
767                 }
768                 Metering::Meter ();
769         }
770 }
771
772 void
773 AudioEngine::set_session (Session *s)
774 {
775         Glib::Threads::Mutex::Lock pl (_process_lock);
776
777         SessionHandlePtr::set_session (s);
778
779         if (_session) {
780
781                 start_metering_thread ();
782
783                 pframes_t blocksize = jack_get_buffer_size (_jack);
784
785                 /* page in as much of the session process code as we
786                    can before we really start running.
787                 */
788
789                 boost::shared_ptr<Ports> p = ports.reader();
790
791                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
792                         i->second->cycle_start (blocksize);
793                 }
794
795                 _session->process (blocksize);
796                 _session->process (blocksize);
797                 _session->process (blocksize);
798                 _session->process (blocksize);
799                 _session->process (blocksize);
800                 _session->process (blocksize);
801                 _session->process (blocksize);
802                 _session->process (blocksize);
803
804                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
805                         i->second->cycle_end (blocksize);
806                 }
807         }
808 }
809
810 void
811 AudioEngine::remove_session ()
812 {
813         Glib::Threads::Mutex::Lock lm (_process_lock);
814
815         if (_running) {
816
817                 stop_metering_thread ();
818
819                 if (_session) {
820                         session_remove_pending = true;
821                         session_removed.wait(_process_lock);
822                 }
823
824         } else {
825                 SessionHandlePtr::set_session (0);
826         }
827
828         remove_all_ports ();
829 }
830
831 void
832 AudioEngine::port_registration_failure (const std::string& portname)
833 {
834         GET_PRIVATE_JACK_POINTER (_jack);
835         string full_portname = jack_client_name;
836         full_portname += ':';
837         full_portname += portname;
838
839
840         jack_port_t* p = jack_port_by_name (_priv_jack, full_portname.c_str());
841         string reason;
842
843         if (p) {
844                 reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
845         } else {
846                 reason = string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with more ports if you need this many tracks."), PROGRAM_NAME);
847         }
848
849         throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
850 }
851
852 boost::shared_ptr<Port>
853 AudioEngine::register_port (DataType dtype, const string& portname, bool input)
854 {
855         boost::shared_ptr<Port> newport;
856
857         try {
858                 if (dtype == DataType::AUDIO) {
859                         newport.reset (new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput)));
860                 } else if (dtype == DataType::MIDI) {
861                         newport.reset (new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput)));
862                 } else {
863                         throw PortRegistrationFailure("unable to create port (unknown type)");
864                 }
865
866                 RCUWriter<Ports> writer (ports);
867                 boost::shared_ptr<Ports> ps = writer.get_copy ();
868                 ps->insert (make_pair (make_port_name_relative (portname), newport));
869
870                 /* writer goes out of scope, forces update */
871
872                 return newport;
873         }
874
875         catch (PortRegistrationFailure& err) {
876                 throw err;
877         } catch (std::exception& e) {
878                 throw PortRegistrationFailure(string_compose(
879                                 _("unable to create port: %1"), e.what()).c_str());
880         } catch (...) {
881                 throw PortRegistrationFailure("unable to create port (unknown error)");
882         }
883 }
884
885 boost::shared_ptr<Port>
886 AudioEngine::register_input_port (DataType type, const string& portname)
887 {
888         return register_port (type, portname, true);
889 }
890
891 boost::shared_ptr<Port>
892 AudioEngine::register_output_port (DataType type, const string& portname)
893 {
894         return register_port (type, portname, false);
895 }
896
897 int
898 AudioEngine::unregister_port (boost::shared_ptr<Port> port)
899 {
900         /* caller must hold process lock */
901
902         if (!_running) {
903                 /* probably happening when the engine has been halted by JACK,
904                    in which case, there is nothing we can do here.
905                    */
906                 return 0;
907         }
908
909         {
910                 RCUWriter<Ports> writer (ports);
911                 boost::shared_ptr<Ports> ps = writer.get_copy ();
912                 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
913
914                 if (x != ps->end()) {
915                         ps->erase (x);
916                 }
917
918                 /* writer goes out of scope, forces update */
919         }
920
921         ports.flush ();
922
923         return 0;
924 }
925
926 int
927 AudioEngine::connect (const string& source, const string& destination)
928 {
929         int ret;
930
931         if (!_running) {
932                 if (!_has_run) {
933                         fatal << _("connect called before engine was started") << endmsg;
934                         /*NOTREACHED*/
935                 } else {
936                         return -1;
937                 }
938         }
939
940         string s = make_port_name_non_relative (source);
941         string d = make_port_name_non_relative (destination);
942
943
944         boost::shared_ptr<Port> src = get_port_by_name (s);
945         boost::shared_ptr<Port> dst = get_port_by_name (d);
946
947         if (src) {
948                 ret = src->connect (d);
949         } else if (dst) {
950                 ret = dst->connect (s);
951         } else {
952                 /* neither port is known to us, and this API isn't intended for use as a general patch bay */
953                 ret = -1;
954         }
955
956         if (ret > 0) {
957                 /* already exists - no error, no warning */
958         } else if (ret < 0) {
959                 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
960                                         source, s, destination, d)
961                       << endmsg;
962         }
963
964         return ret;
965 }
966
967 int
968 AudioEngine::disconnect (const string& source, const string& destination)
969 {
970         int ret;
971
972         if (!_running) {
973                 if (!_has_run) {
974                         fatal << _("disconnect called before engine was started") << endmsg;
975                         /*NOTREACHED*/
976                 } else {
977                         return -1;
978                 }
979         }
980
981         string s = make_port_name_non_relative (source);
982         string d = make_port_name_non_relative (destination);
983
984         boost::shared_ptr<Port> src = get_port_by_name (s);
985         boost::shared_ptr<Port> dst = get_port_by_name (d);
986
987         if (src) {
988                         ret = src->disconnect (d);
989         } else if (dst) {
990                         ret = dst->disconnect (s);
991         } else {
992                 /* neither port is known to us, and this API isn't intended for use as a general patch bay */
993                 ret = -1;
994         }
995         return ret;
996 }
997
998 int
999 AudioEngine::disconnect (boost::shared_ptr<Port> port)
1000 {
1001         GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
1002
1003         if (!_running) {
1004                 if (!_has_run) {
1005                         fatal << _("disconnect called before engine was started") << endmsg;
1006                         /*NOTREACHED*/
1007                 } else {
1008                         return -1;
1009                 }
1010         }
1011
1012         return port->disconnect_all ();
1013 }
1014
1015 ARDOUR::framecnt_t
1016 AudioEngine::frame_rate () const
1017 {
1018         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1019         if (_frame_rate == 0) {
1020                 return (_frame_rate = jack_get_sample_rate (_priv_jack));
1021         } else {
1022                 return _frame_rate;
1023         }
1024 }
1025
1026 size_t
1027 AudioEngine::raw_buffer_size (DataType t)
1028 {
1029         std::map<DataType,size_t>::const_iterator s = _raw_buffer_sizes.find(t);
1030         return (s != _raw_buffer_sizes.end()) ? s->second : 0;
1031 }
1032
1033 ARDOUR::pframes_t
1034 AudioEngine::frames_per_cycle () const
1035 {
1036         GET_PRIVATE_JACK_POINTER_RET (_jack,0);
1037         if (_buffer_size == 0) {
1038                 return jack_get_buffer_size (_jack);
1039         } else {
1040                 return _buffer_size;
1041         }
1042 }
1043
1044 /** @param name Full or short name of port
1045  *  @return Corresponding Port or 0.
1046  */
1047
1048 boost::shared_ptr<Port>
1049 AudioEngine::get_port_by_name (const string& portname)
1050 {
1051         if (!_running) {
1052                 if (!_has_run) {
1053                         fatal << _("get_port_by_name() called before engine was started") << endmsg;
1054                         /*NOTREACHED*/
1055                 } else {
1056                         boost::shared_ptr<Port> ();
1057                 }
1058         }
1059
1060         if (!port_is_mine (portname)) {
1061                 /* not an ardour port */
1062                 return boost::shared_ptr<Port> ();
1063         }
1064
1065         boost::shared_ptr<Ports> pr = ports.reader();
1066         std::string rel = make_port_name_relative (portname);
1067         Ports::iterator x = pr->find (rel);
1068
1069         if (x != pr->end()) {
1070                 /* its possible that the port was renamed by some 3rd party and
1071                    we don't know about it. check for this (the check is quick
1072                    and cheap), and if so, rename the port (which will alter
1073                    the port map as a side effect).
1074                 */
1075                 const std::string check = make_port_name_relative (jack_port_name (x->second->jack_port()));
1076                 if (check != rel) {
1077                         x->second->set_name (check);
1078                 }
1079                 return x->second;
1080         }
1081
1082         return boost::shared_ptr<Port> ();
1083 }
1084
1085 void
1086 AudioEngine::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
1087 {
1088         RCUWriter<Ports> writer (ports);
1089         boost::shared_ptr<Ports> p = writer.get_copy();
1090         Ports::iterator x = p->find (old_relative_name);
1091         
1092         if (x != p->end()) {
1093                 boost::shared_ptr<Port> port = x->second;
1094                 p->erase (x);
1095                 p->insert (make_pair (new_relative_name, port));
1096         }
1097 }
1098
1099 const char **
1100 AudioEngine::get_ports (const string& port_name_pattern, const string& type_name_pattern, uint32_t flags)
1101 {
1102         GET_PRIVATE_JACK_POINTER_RET (_jack,0);
1103         if (!_running) {
1104                 if (!_has_run) {
1105                         fatal << _("get_ports called before engine was started") << endmsg;
1106                         /*NOTREACHED*/
1107                 } else {
1108                         return 0;
1109                 }
1110         }
1111         return jack_get_ports (_priv_jack, port_name_pattern.c_str(), type_name_pattern.c_str(), flags);
1112 }
1113
1114 void
1115 AudioEngine::halted_info (jack_status_t code, const char* reason, void *arg)
1116 {
1117         /* called from jack shutdown handler  */
1118
1119         AudioEngine* ae = static_cast<AudioEngine *> (arg);
1120         bool was_running = ae->_running;
1121
1122         ae->stop_metering_thread ();
1123
1124         ae->_running = false;
1125         ae->_buffer_size = 0;
1126         ae->_frame_rate = 0;
1127         ae->_jack = 0;
1128
1129         if (was_running) {
1130                 MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
1131 #ifdef HAVE_JACK_ON_INFO_SHUTDOWN
1132                 switch (code) {
1133                 case JackBackendError:
1134                         ae->Halted(reason); /* EMIT SIGNAL */
1135                         break;
1136                 default:
1137                         ae->Halted(""); /* EMIT SIGNAL */
1138                 }
1139 #else
1140                 ae->Halted(""); /* EMIT SIGNAL */
1141 #endif
1142         }
1143 }
1144
1145 void
1146 AudioEngine::halted (void *arg)
1147 {
1148         cerr << "HALTED by JACK\n";
1149
1150         /* called from jack shutdown handler  */
1151
1152         AudioEngine* ae = static_cast<AudioEngine *> (arg);
1153         bool was_running = ae->_running;
1154
1155         ae->stop_metering_thread ();
1156
1157         ae->_running = false;
1158         ae->_buffer_size = 0;
1159         ae->_frame_rate = 0;
1160         ae->_jack = 0;
1161
1162         if (was_running) {
1163                 MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
1164                 ae->Halted(""); /* EMIT SIGNAL */
1165         }
1166 }
1167
1168 void
1169 AudioEngine::died ()
1170 {
1171         /* called from a signal handler for SIGPIPE */
1172
1173         stop_metering_thread ();
1174
1175         _running = false;
1176         _buffer_size = 0;
1177         _frame_rate = 0;
1178         _jack = 0;
1179 }
1180
1181 bool
1182 AudioEngine::can_request_hardware_monitoring ()
1183 {
1184         GET_PRIVATE_JACK_POINTER_RET (_jack,false);
1185         const char ** ports;
1186
1187         if ((ports = jack_get_ports (_priv_jack, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortCanMonitor)) == 0) {
1188                 return false;
1189         }
1190
1191         free (ports);
1192
1193         return true;
1194 }
1195
1196 ChanCount
1197 AudioEngine::n_physical (unsigned long flags) const
1198 {
1199         ChanCount c;
1200
1201         GET_PRIVATE_JACK_POINTER_RET (_jack, c);
1202
1203         const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
1204         if (ports == 0) {
1205                 return c;
1206         }
1207
1208         for (uint32_t i = 0; ports[i]; ++i) {
1209                 if (!strstr (ports[i], "Midi-Through")) {
1210                         DataType t (jack_port_type (jack_port_by_name (_jack, ports[i])));
1211                         c.set (t, c.get (t) + 1);
1212                 }
1213         }
1214
1215         free (ports);
1216
1217         return c;
1218 }
1219
1220 ChanCount
1221 AudioEngine::n_physical_inputs () const
1222 {
1223         return n_physical (JackPortIsInput);
1224 }
1225
1226 ChanCount
1227 AudioEngine::n_physical_outputs () const
1228 {
1229         return n_physical (JackPortIsOutput);
1230 }
1231
1232 void
1233 AudioEngine::get_physical (DataType type, unsigned long flags, vector<string>& phy)
1234 {
1235         GET_PRIVATE_JACK_POINTER (_jack);
1236         const char ** ports;
1237
1238         if ((ports = jack_get_ports (_priv_jack, NULL, type.to_jack_type(), JackPortIsPhysical | flags)) == 0) {
1239                 return;
1240         }
1241
1242         if (ports) {
1243                 for (uint32_t i = 0; ports[i]; ++i) {
1244                         if (strstr (ports[i], "Midi-Through")) {
1245                                 continue;
1246                         }
1247                         phy.push_back (ports[i]);
1248                 }
1249                 free (ports);
1250         }
1251 }
1252
1253 /** Get physical ports for which JackPortIsOutput is set; ie those that correspond to
1254  *  a physical input connector.
1255  */
1256 void
1257 AudioEngine::get_physical_inputs (DataType type, vector<string>& ins)
1258 {
1259         get_physical (type, JackPortIsOutput, ins);
1260 }
1261
1262 /** Get physical ports for which JackPortIsInput is set; ie those that correspond to
1263  *  a physical output connector.
1264  */
1265 void
1266 AudioEngine::get_physical_outputs (DataType type, vector<string>& outs)
1267 {
1268         get_physical (type, JackPortIsInput, outs);
1269 }
1270
1271 void
1272 AudioEngine::transport_stop ()
1273 {
1274         GET_PRIVATE_JACK_POINTER (_jack);
1275         jack_transport_stop (_priv_jack);
1276 }
1277
1278 void
1279 AudioEngine::transport_start ()
1280 {
1281         GET_PRIVATE_JACK_POINTER (_jack);
1282         jack_transport_start (_priv_jack);
1283 }
1284
1285 void
1286 AudioEngine::transport_locate (framepos_t where)
1287 {
1288         GET_PRIVATE_JACK_POINTER (_jack);
1289         jack_transport_locate (_priv_jack, where);
1290 }
1291
1292 AudioEngine::TransportState
1293 AudioEngine::transport_state ()
1294 {
1295         GET_PRIVATE_JACK_POINTER_RET (_jack, ((TransportState) JackTransportStopped));
1296         jack_position_t pos;
1297         return (TransportState) jack_transport_query (_priv_jack, &pos);
1298 }
1299
1300 int
1301 AudioEngine::reset_timebase ()
1302 {
1303         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1304         if (_session) {
1305                 if (_session->config.get_jack_time_master()) {
1306                         return jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
1307                 } else {
1308                         return jack_release_timebase (_jack);
1309                 }
1310         }
1311         return 0;
1312 }
1313
1314 int
1315 AudioEngine::freewheel (bool onoff)
1316 {
1317         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1318
1319         if (onoff != _freewheeling) {
1320                 return jack_set_freewheel (_priv_jack, onoff);
1321
1322         } else {
1323                 /* already doing what has been asked for */
1324                 return 0;
1325         }
1326 }
1327
1328 void
1329 AudioEngine::remove_all_ports ()
1330 {
1331         /* make sure that JACK callbacks that will be invoked as we cleanup
1332          * ports know that they have nothing to do.
1333          */
1334
1335         port_remove_in_progress = true;
1336
1337         /* process lock MUST be held by caller
1338         */
1339
1340         {
1341                 RCUWriter<Ports> writer (ports);
1342                 boost::shared_ptr<Ports> ps = writer.get_copy ();
1343                 ps->clear ();
1344         }
1345
1346         /* clear dead wood list in RCU */
1347
1348         ports.flush ();
1349
1350         port_remove_in_progress = false;
1351 }
1352
1353 int
1354 AudioEngine::connect_to_jack (string client_name, string session_uuid)
1355 {
1356         EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
1357         boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
1358         jack_status_t status;
1359
1360         /* revert all environment settings back to whatever they were when ardour started
1361          */
1362
1363         if (global_epa) {
1364                 current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
1365                 global_epa->restore ();
1366         }
1367
1368         jack_client_name = client_name; /* might be reset below */
1369 #ifdef HAVE_JACK_SESSION
1370         if (! session_uuid.empty())
1371             _jack = jack_client_open (jack_client_name.c_str(), JackSessionID, &status, session_uuid.c_str());
1372         else
1373 #endif
1374         _jack = jack_client_open (jack_client_name.c_str(), JackNullOption, &status, 0);
1375
1376         if (_jack == NULL) {
1377                 // error message is not useful here
1378                 return -1;
1379         }
1380
1381         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1382
1383         if (status & JackNameNotUnique) {
1384                 jack_client_name = jack_get_client_name (_priv_jack);
1385         }
1386
1387         return 0;
1388 }
1389
1390 int
1391 AudioEngine::disconnect_from_jack ()
1392 {
1393         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1394
1395         if (_running) {
1396                 stop_metering_thread ();
1397         }
1398
1399         {
1400                 Glib::Threads::Mutex::Lock lm (_process_lock);
1401                 jack_client_close (_priv_jack);
1402                 _jack = 0;
1403         }
1404
1405         _buffer_size = 0;
1406         _frame_rate = 0;
1407         _raw_buffer_sizes.clear();
1408
1409         if (_running) {
1410                 _running = false;
1411                 MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
1412                 Stopped(); /* EMIT SIGNAL */
1413         }
1414
1415         return 0;
1416 }
1417
1418 int
1419 AudioEngine::reconnect_to_jack ()
1420 {
1421         if (_running) {
1422                 disconnect_from_jack ();
1423                 /* XXX give jackd a chance */
1424                 Glib::usleep (250000);
1425         }
1426
1427         if (connect_to_jack (jack_client_name, "")) {
1428                 error << _("failed to connect to JACK") << endmsg;
1429                 return -1;
1430         }
1431
1432         Ports::iterator i;
1433
1434         boost::shared_ptr<Ports> p = ports.reader ();
1435
1436         for (i = p->begin(); i != p->end(); ++i) {
1437                 if (i->second->reestablish ()) {
1438                         break;
1439                 }
1440         }
1441
1442         if (i != p->end()) {
1443                 /* failed */
1444                 remove_all_ports ();
1445                 return -1;
1446         }
1447
1448         GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
1449
1450         MIDI::Manager::instance()->reestablish (_priv_jack);
1451
1452         if (_session) {
1453                 _session->reset_jack_connection (_priv_jack);
1454                 jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
1455                 _session->set_frame_rate (jack_get_sample_rate (_priv_jack));
1456         }
1457
1458         last_monitor_check = 0;
1459
1460         set_jack_callbacks ();
1461
1462         if (jack_activate (_priv_jack) == 0) {
1463                 _running = true;
1464                 _has_run = true;
1465         } else {
1466                 return -1;
1467         }
1468
1469         /* re-establish connections */
1470
1471         for (i = p->begin(); i != p->end(); ++i) {
1472                 i->second->reconnect ();
1473         }
1474
1475         MIDI::Manager::instance()->reconnect ();
1476
1477         Running (); /* EMIT SIGNAL*/
1478
1479         start_metering_thread ();
1480
1481         return 0;
1482 }
1483
1484 int
1485 AudioEngine::request_buffer_size (pframes_t nframes)
1486 {
1487         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1488
1489         if (nframes == jack_get_buffer_size (_priv_jack)) {
1490                 return 0;
1491         }
1492
1493         return jack_set_buffer_size (_priv_jack, nframes);
1494 }
1495
1496 string
1497 AudioEngine::make_port_name_relative (string portname) const
1498 {
1499         string::size_type len;
1500         string::size_type n;
1501
1502         len = portname.length();
1503
1504         for (n = 0; n < len; ++n) {
1505                 if (portname[n] == ':') {
1506                         break;
1507                 }
1508         }
1509
1510         if ((n != len) && (portname.substr (0, n) == jack_client_name)) {
1511                 return portname.substr (n+1);
1512         }
1513
1514         return portname;
1515 }
1516
1517 string
1518 AudioEngine::make_port_name_non_relative (string portname) const
1519 {
1520         string str;
1521
1522         if (portname.find_first_of (':') != string::npos) {
1523                 return portname;
1524         }
1525
1526         str  = jack_client_name;
1527         str += ':';
1528         str += portname;
1529
1530         return str;
1531 }
1532
1533 bool
1534 AudioEngine::port_is_mine (const string& portname) const
1535 {
1536         if (portname.find_first_of (':') != string::npos) {
1537                 if (portname.substr (0, jack_client_name.length ()) != jack_client_name) {
1538                         return false;
1539                 }
1540         }
1541         return true;
1542 }
1543
1544 bool
1545 AudioEngine::is_realtime () const
1546 {
1547         GET_PRIVATE_JACK_POINTER_RET (_jack,false);
1548         return jack_is_realtime (_priv_jack);
1549 }
1550
1551 int
1552 AudioEngine::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
1553 {
1554         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1555         ThreadData* td = new ThreadData (this, f, stacksize);
1556
1557         if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
1558                                        jack_is_realtime (_priv_jack), _start_process_thread, td)) {
1559                 return -1;
1560         }
1561
1562         return 0;
1563 }
1564
1565 void*
1566 AudioEngine::_start_process_thread (void* arg)
1567 {
1568         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
1569         boost::function<void()> f = td->f;
1570         delete td;
1571
1572         f ();
1573
1574         return 0;
1575 }
1576
1577 bool
1578 AudioEngine::port_is_physical (const std::string& portname) const
1579 {
1580         GET_PRIVATE_JACK_POINTER_RET(_jack, false);
1581
1582         jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
1583
1584         if (!port) {
1585                 return false;
1586         }
1587
1588         return jack_port_flags (port) & JackPortIsPhysical;
1589 }
1590
1591 void
1592 AudioEngine::request_jack_monitors_input (const std::string& portname, bool yn) const
1593 {
1594         GET_PRIVATE_JACK_POINTER(_jack);
1595
1596         jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
1597
1598         if (!port) {
1599                 return;
1600         }
1601
1602         jack_port_request_monitor (port, yn);
1603 }
1604
1605 void
1606 AudioEngine::update_latencies ()
1607 {
1608         if (jack_recompute_total_latencies) {
1609                 GET_PRIVATE_JACK_POINTER (_jack);
1610                 jack_recompute_total_latencies (_priv_jack);
1611         }
1612 }
1613
1614 void
1615 AudioEngine::destroy ()
1616 {
1617         delete _instance;
1618         _instance = 0;
1619 }
1620