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