remove b0rked attempt at meter-thread regularity.
[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         while (true) {
763                 Glib::usleep (10000);
764                 if (g_atomic_int_get(&m_meter_exit)) {
765                         break;
766                 }
767                 Metering::Meter ();
768         }
769 }
770
771 void
772 AudioEngine::set_session (Session *s)
773 {
774         Glib::Threads::Mutex::Lock pl (_process_lock);
775
776         SessionHandlePtr::set_session (s);
777
778         if (_session) {
779
780                 start_metering_thread ();
781
782                 pframes_t blocksize = jack_get_buffer_size (_jack);
783
784                 /* page in as much of the session process code as we
785                    can before we really start running.
786                 */
787
788                 boost::shared_ptr<Ports> p = ports.reader();
789
790                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
791                         i->second->cycle_start (blocksize);
792                 }
793
794                 _session->process (blocksize);
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
803                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
804                         i->second->cycle_end (blocksize);
805                 }
806         }
807 }
808
809 void
810 AudioEngine::remove_session ()
811 {
812         Glib::Threads::Mutex::Lock lm (_process_lock);
813
814         if (_running) {
815
816                 stop_metering_thread ();
817
818                 if (_session) {
819                         session_remove_pending = true;
820                         session_removed.wait(_process_lock);
821                 }
822
823         } else {
824                 SessionHandlePtr::set_session (0);
825         }
826
827         remove_all_ports ();
828 }
829
830 void
831 AudioEngine::port_registration_failure (const std::string& portname)
832 {
833         GET_PRIVATE_JACK_POINTER (_jack);
834         string full_portname = jack_client_name;
835         full_portname += ':';
836         full_portname += portname;
837
838
839         jack_port_t* p = jack_port_by_name (_priv_jack, full_portname.c_str());
840         string reason;
841
842         if (p) {
843                 reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
844         } else {
845                 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);
846         }
847
848         throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
849 }
850
851 boost::shared_ptr<Port>
852 AudioEngine::register_port (DataType dtype, const string& portname, bool input)
853 {
854         boost::shared_ptr<Port> newport;
855
856         try {
857                 if (dtype == DataType::AUDIO) {
858                         newport.reset (new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput)));
859                 } else if (dtype == DataType::MIDI) {
860                         newport.reset (new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput)));
861                 } else {
862                         throw PortRegistrationFailure("unable to create port (unknown type)");
863                 }
864
865                 RCUWriter<Ports> writer (ports);
866                 boost::shared_ptr<Ports> ps = writer.get_copy ();
867                 ps->insert (make_pair (make_port_name_relative (portname), newport));
868
869                 /* writer goes out of scope, forces update */
870
871                 return newport;
872         }
873
874         catch (PortRegistrationFailure& err) {
875                 throw err;
876         } catch (std::exception& e) {
877                 throw PortRegistrationFailure(string_compose(
878                                 _("unable to create port: %1"), e.what()).c_str());
879         } catch (...) {
880                 throw PortRegistrationFailure("unable to create port (unknown error)");
881         }
882 }
883
884 boost::shared_ptr<Port>
885 AudioEngine::register_input_port (DataType type, const string& portname)
886 {
887         return register_port (type, portname, true);
888 }
889
890 boost::shared_ptr<Port>
891 AudioEngine::register_output_port (DataType type, const string& portname)
892 {
893         return register_port (type, portname, false);
894 }
895
896 int
897 AudioEngine::unregister_port (boost::shared_ptr<Port> port)
898 {
899         /* caller must hold process lock */
900
901         if (!_running) {
902                 /* probably happening when the engine has been halted by JACK,
903                    in which case, there is nothing we can do here.
904                    */
905                 return 0;
906         }
907
908         {
909                 RCUWriter<Ports> writer (ports);
910                 boost::shared_ptr<Ports> ps = writer.get_copy ();
911                 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
912
913                 if (x != ps->end()) {
914                         ps->erase (x);
915                 }
916
917                 /* writer goes out of scope, forces update */
918         }
919
920         ports.flush ();
921
922         return 0;
923 }
924
925 int
926 AudioEngine::connect (const string& source, const string& destination)
927 {
928         int ret;
929
930         if (!_running) {
931                 if (!_has_run) {
932                         fatal << _("connect called before engine was started") << endmsg;
933                         /*NOTREACHED*/
934                 } else {
935                         return -1;
936                 }
937         }
938
939         string s = make_port_name_non_relative (source);
940         string d = make_port_name_non_relative (destination);
941
942
943         boost::shared_ptr<Port> src = get_port_by_name (s);
944         boost::shared_ptr<Port> dst = get_port_by_name (d);
945
946         if (src) {
947                 ret = src->connect (d);
948         } else if (dst) {
949                 ret = dst->connect (s);
950         } else {
951                 /* neither port is known to us, and this API isn't intended for use as a general patch bay */
952                 ret = -1;
953         }
954
955         if (ret > 0) {
956                 /* already exists - no error, no warning */
957         } else if (ret < 0) {
958                 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
959                                         source, s, destination, d)
960                       << endmsg;
961         }
962
963         return ret;
964 }
965
966 int
967 AudioEngine::disconnect (const string& source, const string& destination)
968 {
969         int ret;
970
971         if (!_running) {
972                 if (!_has_run) {
973                         fatal << _("disconnect called before engine was started") << endmsg;
974                         /*NOTREACHED*/
975                 } else {
976                         return -1;
977                 }
978         }
979
980         string s = make_port_name_non_relative (source);
981         string d = make_port_name_non_relative (destination);
982
983         boost::shared_ptr<Port> src = get_port_by_name (s);
984         boost::shared_ptr<Port> dst = get_port_by_name (d);
985
986         if (src) {
987                         ret = src->disconnect (d);
988         } else if (dst) {
989                         ret = dst->disconnect (s);
990         } else {
991                 /* neither port is known to us, and this API isn't intended for use as a general patch bay */
992                 ret = -1;
993         }
994         return ret;
995 }
996
997 int
998 AudioEngine::disconnect (boost::shared_ptr<Port> port)
999 {
1000         GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
1001
1002         if (!_running) {
1003                 if (!_has_run) {
1004                         fatal << _("disconnect called before engine was started") << endmsg;
1005                         /*NOTREACHED*/
1006                 } else {
1007                         return -1;
1008                 }
1009         }
1010
1011         return port->disconnect_all ();
1012 }
1013
1014 ARDOUR::framecnt_t
1015 AudioEngine::frame_rate () const
1016 {
1017         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1018         if (_frame_rate == 0) {
1019                 return (_frame_rate = jack_get_sample_rate (_priv_jack));
1020         } else {
1021                 return _frame_rate;
1022         }
1023 }
1024
1025 size_t
1026 AudioEngine::raw_buffer_size (DataType t)
1027 {
1028         std::map<DataType,size_t>::const_iterator s = _raw_buffer_sizes.find(t);
1029         return (s != _raw_buffer_sizes.end()) ? s->second : 0;
1030 }
1031
1032 ARDOUR::pframes_t
1033 AudioEngine::frames_per_cycle () const
1034 {
1035         GET_PRIVATE_JACK_POINTER_RET (_jack,0);
1036         if (_buffer_size == 0) {
1037                 return jack_get_buffer_size (_jack);
1038         } else {
1039                 return _buffer_size;
1040         }
1041 }
1042
1043 /** @param name Full or short name of port
1044  *  @return Corresponding Port or 0.
1045  */
1046
1047 boost::shared_ptr<Port>
1048 AudioEngine::get_port_by_name (const string& portname)
1049 {
1050         if (!_running) {
1051                 if (!_has_run) {
1052                         fatal << _("get_port_by_name() called before engine was started") << endmsg;
1053                         /*NOTREACHED*/
1054                 } else {
1055                         boost::shared_ptr<Port> ();
1056                 }
1057         }
1058
1059         if (!port_is_mine (portname)) {
1060                 /* not an ardour port */
1061                 return boost::shared_ptr<Port> ();
1062         }
1063
1064         boost::shared_ptr<Ports> pr = ports.reader();
1065         std::string rel = make_port_name_relative (portname);
1066         Ports::iterator x = pr->find (rel);
1067
1068         if (x != pr->end()) {
1069                 /* its possible that the port was renamed by some 3rd party and
1070                    we don't know about it. check for this (the check is quick
1071                    and cheap), and if so, rename the port (which will alter
1072                    the port map as a side effect).
1073                 */
1074                 const std::string check = make_port_name_relative (jack_port_name (x->second->jack_port()));
1075                 if (check != rel) {
1076                         x->second->set_name (check);
1077                 }
1078                 return x->second;
1079         }
1080
1081         return boost::shared_ptr<Port> ();
1082 }
1083
1084 void
1085 AudioEngine::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
1086 {
1087         RCUWriter<Ports> writer (ports);
1088         boost::shared_ptr<Ports> p = writer.get_copy();
1089         Ports::iterator x = p->find (old_relative_name);
1090         
1091         if (x != p->end()) {
1092                 boost::shared_ptr<Port> port = x->second;
1093                 p->erase (x);
1094                 p->insert (make_pair (new_relative_name, port));
1095         }
1096 }
1097
1098 const char **
1099 AudioEngine::get_ports (const string& port_name_pattern, const string& type_name_pattern, uint32_t flags)
1100 {
1101         GET_PRIVATE_JACK_POINTER_RET (_jack,0);
1102         if (!_running) {
1103                 if (!_has_run) {
1104                         fatal << _("get_ports called before engine was started") << endmsg;
1105                         /*NOTREACHED*/
1106                 } else {
1107                         return 0;
1108                 }
1109         }
1110         return jack_get_ports (_priv_jack, port_name_pattern.c_str(), type_name_pattern.c_str(), flags);
1111 }
1112
1113 void
1114 AudioEngine::halted_info (jack_status_t code, const char* reason, void *arg)
1115 {
1116         /* called from jack shutdown handler  */
1117
1118         AudioEngine* ae = static_cast<AudioEngine *> (arg);
1119         bool was_running = ae->_running;
1120
1121         ae->stop_metering_thread ();
1122
1123         ae->_running = false;
1124         ae->_buffer_size = 0;
1125         ae->_frame_rate = 0;
1126         ae->_jack = 0;
1127
1128         if (was_running) {
1129                 MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
1130 #ifdef HAVE_JACK_ON_INFO_SHUTDOWN
1131                 switch (code) {
1132                 case JackBackendError:
1133                         ae->Halted(reason); /* EMIT SIGNAL */
1134                         break;
1135                 default:
1136                         ae->Halted(""); /* EMIT SIGNAL */
1137                 }
1138 #else
1139                 ae->Halted(""); /* EMIT SIGNAL */
1140 #endif
1141         }
1142 }
1143
1144 void
1145 AudioEngine::halted (void *arg)
1146 {
1147         cerr << "HALTED by JACK\n";
1148
1149         /* called from jack shutdown handler  */
1150
1151         AudioEngine* ae = static_cast<AudioEngine *> (arg);
1152         bool was_running = ae->_running;
1153
1154         ae->stop_metering_thread ();
1155
1156         ae->_running = false;
1157         ae->_buffer_size = 0;
1158         ae->_frame_rate = 0;
1159         ae->_jack = 0;
1160
1161         if (was_running) {
1162                 MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
1163                 ae->Halted(""); /* EMIT SIGNAL */
1164         }
1165 }
1166
1167 void
1168 AudioEngine::died ()
1169 {
1170         /* called from a signal handler for SIGPIPE */
1171
1172         stop_metering_thread ();
1173
1174         _running = false;
1175         _buffer_size = 0;
1176         _frame_rate = 0;
1177         _jack = 0;
1178 }
1179
1180 bool
1181 AudioEngine::can_request_hardware_monitoring ()
1182 {
1183         GET_PRIVATE_JACK_POINTER_RET (_jack,false);
1184         const char ** ports;
1185
1186         if ((ports = jack_get_ports (_priv_jack, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortCanMonitor)) == 0) {
1187                 return false;
1188         }
1189
1190         free (ports);
1191
1192         return true;
1193 }
1194
1195 ChanCount
1196 AudioEngine::n_physical (unsigned long flags) const
1197 {
1198         ChanCount c;
1199
1200         GET_PRIVATE_JACK_POINTER_RET (_jack, c);
1201
1202         const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
1203         if (ports == 0) {
1204                 return c;
1205         }
1206
1207         for (uint32_t i = 0; ports[i]; ++i) {
1208                 if (!strstr (ports[i], "Midi-Through")) {
1209                         DataType t (jack_port_type (jack_port_by_name (_jack, ports[i])));
1210                         c.set (t, c.get (t) + 1);
1211                 }
1212         }
1213
1214         free (ports);
1215
1216         return c;
1217 }
1218
1219 ChanCount
1220 AudioEngine::n_physical_inputs () const
1221 {
1222         return n_physical (JackPortIsInput);
1223 }
1224
1225 ChanCount
1226 AudioEngine::n_physical_outputs () const
1227 {
1228         return n_physical (JackPortIsOutput);
1229 }
1230
1231 void
1232 AudioEngine::get_physical (DataType type, unsigned long flags, vector<string>& phy)
1233 {
1234         GET_PRIVATE_JACK_POINTER (_jack);
1235         const char ** ports;
1236
1237         if ((ports = jack_get_ports (_priv_jack, NULL, type.to_jack_type(), JackPortIsPhysical | flags)) == 0) {
1238                 return;
1239         }
1240
1241         if (ports) {
1242                 for (uint32_t i = 0; ports[i]; ++i) {
1243                         if (strstr (ports[i], "Midi-Through")) {
1244                                 continue;
1245                         }
1246                         phy.push_back (ports[i]);
1247                 }
1248                 free (ports);
1249         }
1250 }
1251
1252 /** Get physical ports for which JackPortIsOutput is set; ie those that correspond to
1253  *  a physical input connector.
1254  */
1255 void
1256 AudioEngine::get_physical_inputs (DataType type, vector<string>& ins)
1257 {
1258         get_physical (type, JackPortIsOutput, ins);
1259 }
1260
1261 /** Get physical ports for which JackPortIsInput is set; ie those that correspond to
1262  *  a physical output connector.
1263  */
1264 void
1265 AudioEngine::get_physical_outputs (DataType type, vector<string>& outs)
1266 {
1267         get_physical (type, JackPortIsInput, outs);
1268 }
1269
1270 void
1271 AudioEngine::transport_stop ()
1272 {
1273         GET_PRIVATE_JACK_POINTER (_jack);
1274         jack_transport_stop (_priv_jack);
1275 }
1276
1277 void
1278 AudioEngine::transport_start ()
1279 {
1280         GET_PRIVATE_JACK_POINTER (_jack);
1281         jack_transport_start (_priv_jack);
1282 }
1283
1284 void
1285 AudioEngine::transport_locate (framepos_t where)
1286 {
1287         GET_PRIVATE_JACK_POINTER (_jack);
1288         jack_transport_locate (_priv_jack, where);
1289 }
1290
1291 AudioEngine::TransportState
1292 AudioEngine::transport_state ()
1293 {
1294         GET_PRIVATE_JACK_POINTER_RET (_jack, ((TransportState) JackTransportStopped));
1295         jack_position_t pos;
1296         return (TransportState) jack_transport_query (_priv_jack, &pos);
1297 }
1298
1299 int
1300 AudioEngine::reset_timebase ()
1301 {
1302         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1303         if (_session) {
1304                 if (_session->config.get_jack_time_master()) {
1305                         return jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
1306                 } else {
1307                         return jack_release_timebase (_jack);
1308                 }
1309         }
1310         return 0;
1311 }
1312
1313 int
1314 AudioEngine::freewheel (bool onoff)
1315 {
1316         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1317
1318         if (onoff != _freewheeling) {
1319                 return jack_set_freewheel (_priv_jack, onoff);
1320
1321         } else {
1322                 /* already doing what has been asked for */
1323                 return 0;
1324         }
1325 }
1326
1327 void
1328 AudioEngine::remove_all_ports ()
1329 {
1330         /* make sure that JACK callbacks that will be invoked as we cleanup
1331          * ports know that they have nothing to do.
1332          */
1333
1334         port_remove_in_progress = true;
1335
1336         /* process lock MUST be held by caller
1337         */
1338
1339         {
1340                 RCUWriter<Ports> writer (ports);
1341                 boost::shared_ptr<Ports> ps = writer.get_copy ();
1342                 ps->clear ();
1343         }
1344
1345         /* clear dead wood list in RCU */
1346
1347         ports.flush ();
1348
1349         port_remove_in_progress = false;
1350 }
1351
1352 int
1353 AudioEngine::connect_to_jack (string client_name, string session_uuid)
1354 {
1355         EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
1356         boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
1357         jack_status_t status;
1358
1359         /* revert all environment settings back to whatever they were when ardour started
1360          */
1361
1362         if (global_epa) {
1363                 current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
1364                 global_epa->restore ();
1365         }
1366
1367         jack_client_name = client_name; /* might be reset below */
1368 #ifdef HAVE_JACK_SESSION
1369         if (! session_uuid.empty())
1370             _jack = jack_client_open (jack_client_name.c_str(), JackSessionID, &status, session_uuid.c_str());
1371         else
1372 #endif
1373         _jack = jack_client_open (jack_client_name.c_str(), JackNullOption, &status, 0);
1374
1375         if (_jack == NULL) {
1376                 // error message is not useful here
1377                 return -1;
1378         }
1379
1380         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1381
1382         if (status & JackNameNotUnique) {
1383                 jack_client_name = jack_get_client_name (_priv_jack);
1384         }
1385
1386         return 0;
1387 }
1388
1389 int
1390 AudioEngine::disconnect_from_jack ()
1391 {
1392         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1393
1394         if (_running) {
1395                 stop_metering_thread ();
1396         }
1397
1398         {
1399                 Glib::Threads::Mutex::Lock lm (_process_lock);
1400                 jack_client_close (_priv_jack);
1401                 _jack = 0;
1402         }
1403
1404         _buffer_size = 0;
1405         _frame_rate = 0;
1406         _raw_buffer_sizes.clear();
1407
1408         if (_running) {
1409                 _running = false;
1410                 MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
1411                 Stopped(); /* EMIT SIGNAL */
1412         }
1413
1414         return 0;
1415 }
1416
1417 int
1418 AudioEngine::reconnect_to_jack ()
1419 {
1420         if (_running) {
1421                 disconnect_from_jack ();
1422                 /* XXX give jackd a chance */
1423                 Glib::usleep (250000);
1424         }
1425
1426         if (connect_to_jack (jack_client_name, "")) {
1427                 error << _("failed to connect to JACK") << endmsg;
1428                 return -1;
1429         }
1430
1431         Ports::iterator i;
1432
1433         boost::shared_ptr<Ports> p = ports.reader ();
1434
1435         for (i = p->begin(); i != p->end(); ++i) {
1436                 if (i->second->reestablish ()) {
1437                         break;
1438                 }
1439         }
1440
1441         if (i != p->end()) {
1442                 /* failed */
1443                 remove_all_ports ();
1444                 return -1;
1445         }
1446
1447         GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
1448
1449         MIDI::Manager::instance()->reestablish (_priv_jack);
1450
1451         if (_session) {
1452                 _session->reset_jack_connection (_priv_jack);
1453                 jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
1454                 _session->set_frame_rate (jack_get_sample_rate (_priv_jack));
1455         }
1456
1457         last_monitor_check = 0;
1458
1459         set_jack_callbacks ();
1460
1461         if (jack_activate (_priv_jack) == 0) {
1462                 _running = true;
1463                 _has_run = true;
1464         } else {
1465                 return -1;
1466         }
1467
1468         /* re-establish connections */
1469
1470         for (i = p->begin(); i != p->end(); ++i) {
1471                 i->second->reconnect ();
1472         }
1473
1474         MIDI::Manager::instance()->reconnect ();
1475
1476         Running (); /* EMIT SIGNAL*/
1477
1478         start_metering_thread ();
1479
1480         return 0;
1481 }
1482
1483 int
1484 AudioEngine::request_buffer_size (pframes_t nframes)
1485 {
1486         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1487
1488         if (nframes == jack_get_buffer_size (_priv_jack)) {
1489                 return 0;
1490         }
1491
1492         return jack_set_buffer_size (_priv_jack, nframes);
1493 }
1494
1495 string
1496 AudioEngine::make_port_name_relative (string portname) const
1497 {
1498         string::size_type len;
1499         string::size_type n;
1500
1501         len = portname.length();
1502
1503         for (n = 0; n < len; ++n) {
1504                 if (portname[n] == ':') {
1505                         break;
1506                 }
1507         }
1508
1509         if ((n != len) && (portname.substr (0, n) == jack_client_name)) {
1510                 return portname.substr (n+1);
1511         }
1512
1513         return portname;
1514 }
1515
1516 string
1517 AudioEngine::make_port_name_non_relative (string portname) const
1518 {
1519         string str;
1520
1521         if (portname.find_first_of (':') != string::npos) {
1522                 return portname;
1523         }
1524
1525         str  = jack_client_name;
1526         str += ':';
1527         str += portname;
1528
1529         return str;
1530 }
1531
1532 bool
1533 AudioEngine::port_is_mine (const string& portname) const
1534 {
1535         if (portname.find_first_of (':') != string::npos) {
1536                 if (portname.substr (0, jack_client_name.length ()) != jack_client_name) {
1537                         return false;
1538                 }
1539         }
1540         return true;
1541 }
1542
1543 bool
1544 AudioEngine::is_realtime () const
1545 {
1546         GET_PRIVATE_JACK_POINTER_RET (_jack,false);
1547         return jack_is_realtime (_priv_jack);
1548 }
1549
1550 int
1551 AudioEngine::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
1552 {
1553         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1554         ThreadData* td = new ThreadData (this, f, stacksize);
1555
1556         if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
1557                                        jack_is_realtime (_priv_jack), _start_process_thread, td)) {
1558                 return -1;
1559         }
1560
1561         return 0;
1562 }
1563
1564 void*
1565 AudioEngine::_start_process_thread (void* arg)
1566 {
1567         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
1568         boost::function<void()> f = td->f;
1569         delete td;
1570
1571         f ();
1572
1573         return 0;
1574 }
1575
1576 bool
1577 AudioEngine::port_is_physical (const std::string& portname) const
1578 {
1579         GET_PRIVATE_JACK_POINTER_RET(_jack, false);
1580
1581         jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
1582
1583         if (!port) {
1584                 return false;
1585         }
1586
1587         return jack_port_flags (port) & JackPortIsPhysical;
1588 }
1589
1590 void
1591 AudioEngine::request_jack_monitors_input (const std::string& portname, bool yn) const
1592 {
1593         GET_PRIVATE_JACK_POINTER(_jack);
1594
1595         jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
1596
1597         if (!port) {
1598                 return;
1599         }
1600
1601         jack_port_request_monitor (port, yn);
1602 }
1603
1604 void
1605 AudioEngine::update_latencies ()
1606 {
1607         if (jack_recompute_total_latencies) {
1608                 GET_PRIVATE_JACK_POINTER (_jack);
1609                 jack_recompute_total_latencies (_priv_jack);
1610         }
1611 }
1612
1613 void
1614 AudioEngine::destroy ()
1615 {
1616         delete _instance;
1617         _instance = 0;
1618 }
1619