dramatically speed up the addition of large numbers of busses + tracks. consists...
[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 exporting */
551
552
553         if (_freewheeling && !Freewheel.empty()) {
554                 /* emit the Freewheel signal and stop freewheeling in the event of trouble
555                  */
556                 boost::optional<int> r = Freewheel (nframes);
557                 if (r.get_value_or (0)) {
558                         jack_set_freewheel (_priv_jack, false);
559                 }
560
561         } else {
562                 MIDI::Manager::instance()->cycle_start(nframes);
563
564                 if (_session) {
565                         _session->process (nframes);
566                 }
567
568                 MIDI::Manager::instance()->cycle_end();
569         }
570
571         if (_freewheeling) {
572                 return 0;
573         }
574
575         if (!_running) {
576                 _processed_frames = next_processed_frames;
577                 return 0;
578         }
579
580         if (last_monitor_check + monitor_check_interval < next_processed_frames) {
581
582                 boost::shared_ptr<Ports> p = ports.reader();
583
584                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
585
586                         bool x;
587
588                         if (i->second->last_monitor() != (x = i->second->jack_monitoring_input ())) {
589                                 i->second->set_last_monitor (x);
590                                 /* XXX I think this is dangerous, due to
591                                    a likely mutex in the signal handlers ...
592                                 */
593                                 i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
594                         }
595                 }
596                 last_monitor_check = next_processed_frames;
597         }
598
599         if (_session->silent()) {
600
601                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
602
603                         if (i->second->sends_output()) {
604                                 i->second->get_buffer(nframes).silence(nframes);
605                         }
606                 }
607         }
608
609         if (session_remove_pending && session_removal_countdown) {
610
611                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
612
613                         if (i->second->sends_output()) {
614
615                                 boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
616                                 if (ap) {
617                                         Sample* s = ap->engine_get_whole_audio_buffer ();
618                                         gain_t g = session_removal_gain;
619                                         
620                                         for (pframes_t n = 0; n < nframes; ++n) {
621                                                 *s++ *= g;
622                                                 g -= session_removal_gain_step;
623                                         }
624                                 }
625                         }
626                 }
627                 
628                 if (session_removal_countdown > nframes) {
629                         session_removal_countdown -= nframes;
630                 } else {
631                         session_removal_countdown = 0;
632                 }
633
634                 session_removal_gain -= (nframes * session_removal_gain_step);
635         }
636
637         // Finalize ports
638
639         for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
640                 i->second->cycle_end (nframes);
641         }
642
643         _processed_frames = next_processed_frames;
644
645         PT_TIMING_CHECK (2);
646         
647         return 0;
648 }
649
650 int
651 AudioEngine::_sample_rate_callback (pframes_t nframes, void *arg)
652 {
653         return static_cast<AudioEngine *> (arg)->jack_sample_rate_callback (nframes);
654 }
655
656 int
657 AudioEngine::jack_sample_rate_callback (pframes_t nframes)
658 {
659         _frame_rate = nframes;
660         _usecs_per_cycle = (int) floor ((((double) frames_per_cycle() / nframes)) * 1000000.0);
661
662         /* check for monitor input change every 1/10th of second */
663
664         monitor_check_interval = nframes / 10;
665         last_monitor_check = 0;
666
667         if (_session) {
668                 _session->set_frame_rate (nframes);
669         }
670
671         SampleRateChanged (nframes); /* EMIT SIGNAL */
672
673         return 0;
674 }
675
676 void
677 AudioEngine::jack_latency_callback (jack_latency_callback_mode_t mode)
678 {
679         if (_session) {
680                 _session->update_latency (mode == JackPlaybackLatency);
681         }
682 }
683
684 int
685 AudioEngine::_bufsize_callback (pframes_t nframes, void *arg)
686 {
687         return static_cast<AudioEngine *> (arg)->jack_bufsize_callback (nframes);
688 }
689
690 int
691 AudioEngine::jack_bufsize_callback (pframes_t nframes)
692 {
693         /* if the size has not changed, this should be a no-op */
694
695         if (nframes == _buffer_size) {
696                 return 0;
697         }
698
699         GET_PRIVATE_JACK_POINTER_RET (_jack, 1);
700
701         _buffer_size = nframes;
702         _usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0);
703         last_monitor_check = 0;
704
705         if (jack_port_type_get_buffer_size) {
706                 _raw_buffer_sizes[DataType::AUDIO] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_AUDIO_TYPE);
707                 _raw_buffer_sizes[DataType::MIDI] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_MIDI_TYPE);
708         } else {
709
710                 /* Old version of JACK.
711
712                    These crude guesses, see below where we try to get the right answers.
713
714                    Note that our guess for MIDI deliberatey tries to overestimate
715                    by a little. It would be nicer if we could get the actual
716                    size from a port, but we have to use this estimate in the
717                    event that there are no MIDI ports currently. If there are
718                    the value will be adjusted below.
719                 */
720
721                 _raw_buffer_sizes[DataType::AUDIO] = nframes * sizeof (Sample);
722                 _raw_buffer_sizes[DataType::MIDI] = nframes * 4 - (nframes/2);
723         }
724
725         {
726                 Glib::Threads::Mutex::Lock lm (_process_lock);
727
728                 boost::shared_ptr<Ports> p = ports.reader();
729
730                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
731                         i->second->reset();
732                 }
733         }
734
735         if (_session) {
736                 _session->set_block_size (_buffer_size);
737         }
738
739         return 0;
740 }
741
742 void
743 AudioEngine::stop_metering_thread ()
744 {
745         if (m_meter_thread) {
746                 g_atomic_int_set (&m_meter_exit, 1);
747                 m_meter_thread->join ();
748                 m_meter_thread = 0;
749         }
750 }
751
752 void
753 AudioEngine::start_metering_thread ()
754 {
755         if (m_meter_thread == 0) {
756                 g_atomic_int_set (&m_meter_exit, 0);
757                 m_meter_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::meter_thread, this));
758         }
759 }
760
761 void
762 AudioEngine::meter_thread ()
763 {
764         pthread_set_name (X_("meter"));
765
766         while (true) {
767                 Glib::usleep (10000); /* 1/100th sec interval */
768                 if (g_atomic_int_get(&m_meter_exit)) {
769                         break;
770                 }
771                 Metering::Meter ();
772         }
773 }
774
775 void
776 AudioEngine::set_session (Session *s)
777 {
778         Glib::Threads::Mutex::Lock pl (_process_lock);
779
780         SessionHandlePtr::set_session (s);
781
782         if (_session) {
783
784                 start_metering_thread ();
785
786                 pframes_t blocksize = jack_get_buffer_size (_jack);
787
788                 /* page in as much of the session process code as we
789                    can before we really start running.
790                 */
791
792                 boost::shared_ptr<Ports> p = ports.reader();
793
794                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
795                         i->second->cycle_start (blocksize);
796                 }
797
798                 _session->process (blocksize);
799                 _session->process (blocksize);
800                 _session->process (blocksize);
801                 _session->process (blocksize);
802                 _session->process (blocksize);
803                 _session->process (blocksize);
804                 _session->process (blocksize);
805                 _session->process (blocksize);
806
807                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
808                         i->second->cycle_end (blocksize);
809                 }
810         }
811 }
812
813 void
814 AudioEngine::remove_session ()
815 {
816         Glib::Threads::Mutex::Lock lm (_process_lock);
817
818         if (_running) {
819
820                 stop_metering_thread ();
821
822                 if (_session) {
823                         session_remove_pending = true;
824                         session_removed.wait(_process_lock);
825                 }
826
827         } else {
828                 SessionHandlePtr::set_session (0);
829         }
830
831         remove_all_ports ();
832 }
833
834 void
835 AudioEngine::port_registration_failure (const std::string& portname)
836 {
837         GET_PRIVATE_JACK_POINTER (_jack);
838         string full_portname = jack_client_name;
839         full_portname += ':';
840         full_portname += portname;
841
842
843         jack_port_t* p = jack_port_by_name (_priv_jack, full_portname.c_str());
844         string reason;
845
846         if (p) {
847                 reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
848         } else {
849                 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);
850         }
851
852         throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
853 }
854
855 boost::shared_ptr<Port>
856 AudioEngine::register_port (DataType dtype, const string& portname, bool input)
857 {
858         boost::shared_ptr<Port> newport;
859
860         try {
861                 if (dtype == DataType::AUDIO) {
862                         newport.reset (new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput)));
863                 } else if (dtype == DataType::MIDI) {
864                         newport.reset (new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput)));
865                 } else {
866                         throw PortRegistrationFailure("unable to create port (unknown type)");
867                 }
868
869                 RCUWriter<Ports> writer (ports);
870                 boost::shared_ptr<Ports> ps = writer.get_copy ();
871                 ps->insert (make_pair (make_port_name_relative (portname), newport));
872
873                 /* writer goes out of scope, forces update */
874
875                 return newport;
876         }
877
878         catch (PortRegistrationFailure& err) {
879                 throw err;
880         } catch (std::exception& e) {
881                 throw PortRegistrationFailure(string_compose(
882                                 _("unable to create port: %1"), e.what()).c_str());
883         } catch (...) {
884                 throw PortRegistrationFailure("unable to create port (unknown error)");
885         }
886 }
887
888 boost::shared_ptr<Port>
889 AudioEngine::register_input_port (DataType type, const string& portname)
890 {
891         return register_port (type, portname, true);
892 }
893
894 boost::shared_ptr<Port>
895 AudioEngine::register_output_port (DataType type, const string& portname)
896 {
897         return register_port (type, portname, false);
898 }
899
900 int
901 AudioEngine::unregister_port (boost::shared_ptr<Port> port)
902 {
903         /* caller must hold process lock */
904
905         if (!_running) {
906                 /* probably happening when the engine has been halted by JACK,
907                    in which case, there is nothing we can do here.
908                    */
909                 return 0;
910         }
911
912         {
913                 RCUWriter<Ports> writer (ports);
914                 boost::shared_ptr<Ports> ps = writer.get_copy ();
915                 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
916
917                 if (x != ps->end()) {
918                         ps->erase (x);
919                 }
920
921                 /* writer goes out of scope, forces update */
922         }
923
924         ports.flush ();
925
926         return 0;
927 }
928
929 int
930 AudioEngine::connect (const string& source, const string& destination)
931 {
932         int ret;
933
934         if (!_running) {
935                 if (!_has_run) {
936                         fatal << _("connect called before engine was started") << endmsg;
937                         /*NOTREACHED*/
938                 } else {
939                         return -1;
940                 }
941         }
942
943         string s = make_port_name_non_relative (source);
944         string d = make_port_name_non_relative (destination);
945
946
947         boost::shared_ptr<Port> src = get_port_by_name (s);
948         boost::shared_ptr<Port> dst = get_port_by_name (d);
949
950         if (src) {
951                 ret = src->connect (d);
952         } else if (dst) {
953                 ret = dst->connect (s);
954         } else {
955                 /* neither port is known to us, and this API isn't intended for use as a general patch bay */
956                 ret = -1;
957         }
958
959         if (ret > 0) {
960                 /* already exists - no error, no warning */
961         } else if (ret < 0) {
962                 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
963                                         source, s, destination, d)
964                       << endmsg;
965         }
966
967         return ret;
968 }
969
970 int
971 AudioEngine::disconnect (const string& source, const string& destination)
972 {
973         int ret;
974
975         if (!_running) {
976                 if (!_has_run) {
977                         fatal << _("disconnect called before engine was started") << endmsg;
978                         /*NOTREACHED*/
979                 } else {
980                         return -1;
981                 }
982         }
983
984         string s = make_port_name_non_relative (source);
985         string d = make_port_name_non_relative (destination);
986
987         boost::shared_ptr<Port> src = get_port_by_name (s);
988         boost::shared_ptr<Port> dst = get_port_by_name (d);
989
990         if (src) {
991                         ret = src->disconnect (d);
992         } else if (dst) {
993                         ret = dst->disconnect (s);
994         } else {
995                 /* neither port is known to us, and this API isn't intended for use as a general patch bay */
996                 ret = -1;
997         }
998         return ret;
999 }
1000
1001 int
1002 AudioEngine::disconnect (boost::shared_ptr<Port> port)
1003 {
1004         GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
1005
1006         if (!_running) {
1007                 if (!_has_run) {
1008                         fatal << _("disconnect called before engine was started") << endmsg;
1009                         /*NOTREACHED*/
1010                 } else {
1011                         return -1;
1012                 }
1013         }
1014
1015         return port->disconnect_all ();
1016 }
1017
1018 ARDOUR::framecnt_t
1019 AudioEngine::frame_rate () const
1020 {
1021         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1022         if (_frame_rate == 0) {
1023                 return (_frame_rate = jack_get_sample_rate (_priv_jack));
1024         } else {
1025                 return _frame_rate;
1026         }
1027 }
1028
1029 size_t
1030 AudioEngine::raw_buffer_size (DataType t)
1031 {
1032         std::map<DataType,size_t>::const_iterator s = _raw_buffer_sizes.find(t);
1033         return (s != _raw_buffer_sizes.end()) ? s->second : 0;
1034 }
1035
1036 ARDOUR::pframes_t
1037 AudioEngine::frames_per_cycle () const
1038 {
1039         GET_PRIVATE_JACK_POINTER_RET (_jack,0);
1040         if (_buffer_size == 0) {
1041                 return jack_get_buffer_size (_jack);
1042         } else {
1043                 return _buffer_size;
1044         }
1045 }
1046
1047 /** @param name Full or short name of port
1048  *  @return Corresponding Port or 0.
1049  */
1050
1051 boost::shared_ptr<Port>
1052 AudioEngine::get_port_by_name (const string& portname)
1053 {
1054         if (!_running) {
1055                 if (!_has_run) {
1056                         fatal << _("get_port_by_name() called before engine was started") << endmsg;
1057                         /*NOTREACHED*/
1058                 } else {
1059                         boost::shared_ptr<Port> ();
1060                 }
1061         }
1062
1063         if (!port_is_mine (portname)) {
1064                 /* not an ardour port */
1065                 return boost::shared_ptr<Port> ();
1066         }
1067
1068         boost::shared_ptr<Ports> pr = ports.reader();
1069         std::string rel = make_port_name_relative (portname);
1070         Ports::iterator x = pr->find (rel);
1071
1072         if (x != pr->end()) {
1073                 /* its possible that the port was renamed by some 3rd party and
1074                    we don't know about it. check for this (the check is quick
1075                    and cheap), and if so, rename the port (which will alter
1076                    the port map as a side effect).
1077                 */
1078                 const std::string check = make_port_name_relative (jack_port_name (x->second->jack_port()));
1079                 if (check != rel) {
1080                         x->second->set_name (check);
1081                 }
1082                 return x->second;
1083         }
1084
1085         return boost::shared_ptr<Port> ();
1086 }
1087
1088 void
1089 AudioEngine::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
1090 {
1091         RCUWriter<Ports> writer (ports);
1092         boost::shared_ptr<Ports> p = writer.get_copy();
1093         Ports::iterator x = p->find (old_relative_name);
1094         
1095         if (x != p->end()) {
1096                 boost::shared_ptr<Port> port = x->second;
1097                 p->erase (x);
1098                 p->insert (make_pair (new_relative_name, port));
1099         }
1100 }
1101
1102 const char **
1103 AudioEngine::get_ports (const string& port_name_pattern, const string& type_name_pattern, uint32_t flags)
1104 {
1105         GET_PRIVATE_JACK_POINTER_RET (_jack,0);
1106         if (!_running) {
1107                 if (!_has_run) {
1108                         fatal << _("get_ports called before engine was started") << endmsg;
1109                         /*NOTREACHED*/
1110                 } else {
1111                         return 0;
1112                 }
1113         }
1114         return jack_get_ports (_priv_jack, port_name_pattern.c_str(), type_name_pattern.c_str(), flags);
1115 }
1116
1117 void
1118 AudioEngine::halted_info (jack_status_t code, const char* reason, void *arg)
1119 {
1120         /* called from jack shutdown handler  */
1121
1122         AudioEngine* ae = static_cast<AudioEngine *> (arg);
1123         bool was_running = ae->_running;
1124
1125         ae->stop_metering_thread ();
1126
1127         ae->_running = false;
1128         ae->_buffer_size = 0;
1129         ae->_frame_rate = 0;
1130         ae->_jack = 0;
1131
1132         if (was_running) {
1133 #ifdef HAVE_JACK_ON_INFO_SHUTDOWN
1134                 switch (code) {
1135                 case JackBackendError:
1136                         ae->Halted(reason); /* EMIT SIGNAL */
1137                         break;
1138                 default:
1139                         ae->Halted(""); /* EMIT SIGNAL */
1140                 }
1141 #else
1142                 ae->Halted(""); /* EMIT SIGNAL */
1143 #endif
1144         }
1145 }
1146
1147 void
1148 AudioEngine::halted (void *arg)
1149 {
1150         cerr << "HALTED by JACK\n";
1151
1152         /* called from jack shutdown handler  */
1153
1154         AudioEngine* ae = static_cast<AudioEngine *> (arg);
1155         bool was_running = ae->_running;
1156
1157         ae->stop_metering_thread ();
1158
1159         ae->_running = false;
1160         ae->_buffer_size = 0;
1161         ae->_frame_rate = 0;
1162         ae->_jack = 0;
1163
1164         if (was_running) {
1165                 MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
1166                 ae->Halted(""); /* EMIT SIGNAL */
1167         }
1168 }
1169
1170 void
1171 AudioEngine::died ()
1172 {
1173         /* called from a signal handler for SIGPIPE */
1174
1175         stop_metering_thread ();
1176
1177         _running = false;
1178         _buffer_size = 0;
1179         _frame_rate = 0;
1180         _jack = 0;
1181 }
1182
1183 bool
1184 AudioEngine::can_request_hardware_monitoring ()
1185 {
1186         GET_PRIVATE_JACK_POINTER_RET (_jack,false);
1187         const char ** ports;
1188
1189         if ((ports = jack_get_ports (_priv_jack, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortCanMonitor)) == 0) {
1190                 return false;
1191         }
1192
1193         free (ports);
1194
1195         return true;
1196 }
1197
1198 ChanCount
1199 AudioEngine::n_physical (unsigned long flags) const
1200 {
1201         ChanCount c;
1202
1203         GET_PRIVATE_JACK_POINTER_RET (_jack, c);
1204
1205         const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
1206         if (ports == 0) {
1207                 return c;
1208         }
1209
1210         for (uint32_t i = 0; ports[i]; ++i) {
1211                 if (!strstr (ports[i], "Midi-Through")) {
1212                         DataType t (jack_port_type (jack_port_by_name (_jack, ports[i])));
1213                         c.set (t, c.get (t) + 1);
1214                 }
1215         }
1216
1217         free (ports);
1218
1219         return c;
1220 }
1221
1222 ChanCount
1223 AudioEngine::n_physical_inputs () const
1224 {
1225         return n_physical (JackPortIsInput);
1226 }
1227
1228 ChanCount
1229 AudioEngine::n_physical_outputs () const
1230 {
1231         return n_physical (JackPortIsOutput);
1232 }
1233
1234 void
1235 AudioEngine::get_physical (DataType type, unsigned long flags, vector<string>& phy)
1236 {
1237         GET_PRIVATE_JACK_POINTER (_jack);
1238         const char ** ports;
1239
1240         if ((ports = jack_get_ports (_priv_jack, NULL, type.to_jack_type(), JackPortIsPhysical | flags)) == 0) {
1241                 return;
1242         }
1243
1244         if (ports) {
1245                 for (uint32_t i = 0; ports[i]; ++i) {
1246                         if (strstr (ports[i], "Midi-Through")) {
1247                                 continue;
1248                         }
1249                         phy.push_back (ports[i]);
1250                 }
1251                 free (ports);
1252         }
1253 }
1254
1255 /** Get physical ports for which JackPortIsOutput is set; ie those that correspond to
1256  *  a physical input connector.
1257  */
1258 void
1259 AudioEngine::get_physical_inputs (DataType type, vector<string>& ins)
1260 {
1261         get_physical (type, JackPortIsOutput, ins);
1262 }
1263
1264 /** Get physical ports for which JackPortIsInput is set; ie those that correspond to
1265  *  a physical output connector.
1266  */
1267 void
1268 AudioEngine::get_physical_outputs (DataType type, vector<string>& outs)
1269 {
1270         get_physical (type, JackPortIsInput, outs);
1271 }
1272
1273 void
1274 AudioEngine::transport_stop ()
1275 {
1276         GET_PRIVATE_JACK_POINTER (_jack);
1277         jack_transport_stop (_priv_jack);
1278 }
1279
1280 void
1281 AudioEngine::transport_start ()
1282 {
1283         GET_PRIVATE_JACK_POINTER (_jack);
1284         jack_transport_start (_priv_jack);
1285 }
1286
1287 void
1288 AudioEngine::transport_locate (framepos_t where)
1289 {
1290         GET_PRIVATE_JACK_POINTER (_jack);
1291         jack_transport_locate (_priv_jack, where);
1292 }
1293
1294 AudioEngine::TransportState
1295 AudioEngine::transport_state ()
1296 {
1297         GET_PRIVATE_JACK_POINTER_RET (_jack, ((TransportState) JackTransportStopped));
1298         jack_position_t pos;
1299         return (TransportState) jack_transport_query (_priv_jack, &pos);
1300 }
1301
1302 int
1303 AudioEngine::reset_timebase ()
1304 {
1305         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1306         if (_session) {
1307                 if (_session->config.get_jack_time_master()) {
1308                         return jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
1309                 } else {
1310                         return jack_release_timebase (_jack);
1311                 }
1312         }
1313         return 0;
1314 }
1315
1316 int
1317 AudioEngine::freewheel (bool onoff)
1318 {
1319         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1320
1321         if (onoff != _freewheeling) {
1322                 return jack_set_freewheel (_priv_jack, onoff);
1323
1324         } else {
1325                 /* already doing what has been asked for */
1326                 return 0;
1327         }
1328 }
1329
1330 void
1331 AudioEngine::remove_all_ports ()
1332 {
1333         /* make sure that JACK callbacks that will be invoked as we cleanup
1334          * ports know that they have nothing to do.
1335          */
1336
1337         port_remove_in_progress = true;
1338
1339         /* process lock MUST be held by caller
1340         */
1341
1342         {
1343                 RCUWriter<Ports> writer (ports);
1344                 boost::shared_ptr<Ports> ps = writer.get_copy ();
1345                 ps->clear ();
1346         }
1347
1348         /* clear dead wood list in RCU */
1349
1350         ports.flush ();
1351
1352         port_remove_in_progress = false;
1353 }
1354
1355 int
1356 AudioEngine::connect_to_jack (string client_name, string session_uuid)
1357 {
1358         EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
1359         boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
1360         jack_status_t status;
1361
1362         /* revert all environment settings back to whatever they were when ardour started
1363          */
1364
1365         if (global_epa) {
1366                 current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
1367                 global_epa->restore ();
1368         }
1369
1370         jack_client_name = client_name; /* might be reset below */
1371 #ifdef HAVE_JACK_SESSION
1372         if (! session_uuid.empty())
1373             _jack = jack_client_open (jack_client_name.c_str(), JackSessionID, &status, session_uuid.c_str());
1374         else
1375 #endif
1376         _jack = jack_client_open (jack_client_name.c_str(), JackNullOption, &status, 0);
1377
1378         if (_jack == NULL) {
1379                 // error message is not useful here
1380                 return -1;
1381         }
1382
1383         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1384
1385         if (status & JackNameNotUnique) {
1386                 jack_client_name = jack_get_client_name (_priv_jack);
1387         }
1388
1389         return 0;
1390 }
1391
1392 int
1393 AudioEngine::disconnect_from_jack ()
1394 {
1395         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1396
1397         if (_running) {
1398                 stop_metering_thread ();
1399         }
1400
1401         {
1402                 Glib::Threads::Mutex::Lock lm (_process_lock);
1403                 jack_client_close (_priv_jack);
1404                 _jack = 0;
1405         }
1406
1407         _buffer_size = 0;
1408         _frame_rate = 0;
1409         _raw_buffer_sizes.clear();
1410
1411         if (_running) {
1412                 _running = false;
1413                 MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
1414                 Stopped(); /* EMIT SIGNAL */
1415         }
1416
1417         return 0;
1418 }
1419
1420 int
1421 AudioEngine::reconnect_to_jack ()
1422 {
1423         if (_running) {
1424                 disconnect_from_jack ();
1425                 /* XXX give jackd a chance */
1426                 Glib::usleep (250000);
1427         }
1428
1429         if (connect_to_jack (jack_client_name, "")) {
1430                 error << _("failed to connect to JACK") << endmsg;
1431                 return -1;
1432         }
1433
1434         Ports::iterator i;
1435
1436         boost::shared_ptr<Ports> p = ports.reader ();
1437
1438         for (i = p->begin(); i != p->end(); ++i) {
1439                 if (i->second->reestablish ()) {
1440                         break;
1441                 }
1442         }
1443
1444         if (i != p->end()) {
1445                 /* failed */
1446                 remove_all_ports ();
1447                 return -1;
1448         }
1449
1450         GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
1451
1452         MIDI::Manager::instance()->reestablish (_priv_jack);
1453
1454         if (_session) {
1455                 _session->reset_jack_connection (_priv_jack);
1456                 jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
1457                 _session->set_frame_rate (jack_get_sample_rate (_priv_jack));
1458         }
1459
1460         last_monitor_check = 0;
1461
1462         set_jack_callbacks ();
1463
1464         if (jack_activate (_priv_jack) == 0) {
1465                 _running = true;
1466                 _has_run = true;
1467         } else {
1468                 return -1;
1469         }
1470
1471         /* re-establish connections */
1472
1473         for (i = p->begin(); i != p->end(); ++i) {
1474                 i->second->reconnect ();
1475         }
1476
1477         MIDI::Manager::instance()->reconnect ();
1478
1479         Running (); /* EMIT SIGNAL*/
1480
1481         start_metering_thread ();
1482
1483         return 0;
1484 }
1485
1486 int
1487 AudioEngine::request_buffer_size (pframes_t nframes)
1488 {
1489         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
1490
1491         if (nframes == jack_get_buffer_size (_priv_jack)) {
1492                 return 0;
1493         }
1494
1495         return jack_set_buffer_size (_priv_jack, nframes);
1496 }
1497
1498 string
1499 AudioEngine::make_port_name_relative (string portname) const
1500 {
1501         string::size_type len;
1502         string::size_type n;
1503
1504         len = portname.length();
1505
1506         for (n = 0; n < len; ++n) {
1507                 if (portname[n] == ':') {
1508                         break;
1509                 }
1510         }
1511
1512         if ((n != len) && (portname.substr (0, n) == jack_client_name)) {
1513                 return portname.substr (n+1);
1514         }
1515
1516         return portname;
1517 }
1518
1519 string
1520 AudioEngine::make_port_name_non_relative (string portname) const
1521 {
1522         string str;
1523
1524         if (portname.find_first_of (':') != string::npos) {
1525                 return portname;
1526         }
1527
1528         str  = jack_client_name;
1529         str += ':';
1530         str += portname;
1531
1532         return str;
1533 }
1534
1535 bool
1536 AudioEngine::port_is_mine (const string& portname) const
1537 {
1538         if (portname.find_first_of (':') != string::npos) {
1539                 if (portname.substr (0, jack_client_name.length ()) != jack_client_name) {
1540                         return false;
1541                 }
1542         }
1543         return true;
1544 }
1545
1546 bool
1547 AudioEngine::is_realtime () const
1548 {
1549         GET_PRIVATE_JACK_POINTER_RET (_jack,false);
1550         return jack_is_realtime (_priv_jack);
1551 }
1552
1553 int
1554 AudioEngine::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
1555 {
1556         GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
1557         ThreadData* td = new ThreadData (this, f, stacksize);
1558
1559         if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
1560                                        jack_is_realtime (_priv_jack), _start_process_thread, td)) {
1561                 return -1;
1562         }
1563
1564         return 0;
1565 }
1566
1567 void*
1568 AudioEngine::_start_process_thread (void* arg)
1569 {
1570         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
1571         boost::function<void()> f = td->f;
1572         delete td;
1573
1574         f ();
1575
1576         return 0;
1577 }
1578
1579 bool
1580 AudioEngine::port_is_physical (const std::string& portname) const
1581 {
1582         GET_PRIVATE_JACK_POINTER_RET(_jack, false);
1583
1584         jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
1585
1586         if (!port) {
1587                 return false;
1588         }
1589
1590         return jack_port_flags (port) & JackPortIsPhysical;
1591 }
1592
1593 void
1594 AudioEngine::request_jack_monitors_input (const std::string& portname, bool yn) const
1595 {
1596         GET_PRIVATE_JACK_POINTER(_jack);
1597
1598         jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
1599
1600         if (!port) {
1601                 return;
1602         }
1603
1604         jack_port_request_monitor (port, yn);
1605 }
1606
1607 void
1608 AudioEngine::update_latencies ()
1609 {
1610         if (jack_recompute_total_latencies) {
1611                 GET_PRIVATE_JACK_POINTER (_jack);
1612                 jack_recompute_total_latencies (_priv_jack);
1613         }
1614 }
1615
1616 void
1617 AudioEngine::destroy ()
1618 {
1619         delete _instance;
1620         _instance = 0;
1621 }
1622