full compilation and linking (coding not finished, will not run)
[ardour.git] / libs / ardour / jack_audiobackend.cc
index 2d614a80a04549c9e8763570be437019ecd14295..04ee94a80ce74642ccaa6c8db9fd13a26999b2fb 100644 (file)
+/*
+    Copyright (C) 2013 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <math.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <glibmm/timer.h>
+
+#include "pbd/error.h"
+
+#include "midi++/manager.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/types.h"
 #include "ardour/jack_audiobackend.h"
+#include "ardour/jack_connection.h"
+#include "ardour/jack_portengine.h"
 
-#define GET_PRIVATE_JACK_POINTER(j)  jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return; }
-#define GET_PRIVATE_JACK_POINTER_RET(j,r) jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return r; }
+#include "i18n.h"
 
-int
-JACKAudioBackend::start ()
+using namespace ARDOUR;
+using namespace PBD;
+using std::string;
+using std::vector;
+
+#define GET_PRIVATE_JACK_POINTER(localvar)  jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
+#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
+
+JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnection> jc)
+       : AudioBackend (e)
+       , _jack_connection (jc)
+       , _running (false)
+       , _freewheeling (false)
+       , _target_sample_rate (48000)
+       , _target_buffer_size (1024)
+       , _target_sample_format (FormatFloat)
+       , _target_interleaved (false)
+       , _target_input_channels (-1)
+       , _target_output_channels (-1)
+       , _target_systemic_input_latency (0)
+       , _target_systemic_output_latency (0)
 {
-       Glib::Threads::Mutex::Lock lm (_state_lock);
+}
 
-       if (running()) {
-               /* already running */
-               return 1;
-       }
+string
+JACKAudioBackend::name() const 
+{
+       return X_("JACK");
 }
 
-int
-JACKAudioBackend::stop ()
+void*
+JACKAudioBackend::private_handle() const
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
+       return _jack_connection->jack();
+}
 
-       {
-               Glib::Threads::Mutex::Lock lm (_process_lock);
-               jack_client_close (_priv_jack);
-               _jack = 0;
+bool
+JACKAudioBackend::connected() const
+{
+       return (private_handle() != 0);
+}
+
+bool
+JACKAudioBackend::is_realtime () const
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack,false);
+       return jack_is_realtime (_priv_jack);
+}
+
+vector<string>
+JACKAudioBackend::enumerate_devices () const
+{
+       vector<string> devices;
+       return devices;
+}
+
+vector<float>
+JACKAudioBackend::available_sample_rates (const string& /*device*/) const
+{
+       vector<float> f;
+       
+       if (connected()) {
+               f.push_back (sample_rate());
+               return f;
+       }
+
+       /* if JACK is not already running, just list a bunch of reasonable 
+          values and let the future sort it all out.
+       */
+
+       f.push_back (8000.0);
+       f.push_back (16000.0);
+       f.push_back (24000.0);
+       f.push_back (32000.0);
+       f.push_back (44100.0);
+       f.push_back (48000.0);
+       f.push_back (88200.0);
+       f.push_back (96000.0);
+       f.push_back (192000.0);
+       f.push_back (384000.0);
+       
+       return f;
+}
+
+vector<uint32_t>
+JACKAudioBackend::available_buffer_sizes (const string& /*device*/) const
+{
+       vector<uint32_t> s;
+       
+       if (connected()) {
+               s.push_back (buffer_size());
+               return s;
        }
 
-       _buffer_size = 0;
-       _frame_rate = 0;
-       _raw_buffer_sizes.clear();
+       s.push_back (8);
+       s.push_back (16);
+       s.push_back (32);
+       s.push_back (64);
+       s.push_back (128);
+       s.push_back (256);
+       s.push_back (512);
+       s.push_back (1024);
+       s.push_back (2048);
+       s.push_back (4096);
+       s.push_back (8192);
 
+       return s;
+}
+
+uint32_t
+JACKAudioBackend::available_input_channel_count (const string& /*device*/) const
+{
+       return 128;
+}
+
+uint32_t
+JACKAudioBackend::available_output_channel_count (const string& /*device*/) const
+{
+       return 128;
+}
+
+/* -- parameter setting -- */
+
+int
+JACKAudioBackend::set_device_name (const string& dev)
+{
+       if (connected()) {
+               /* need to stop and restart JACK for this to work, at present */
+               return -1;
+       }
+
+       _target_device = dev;
        return 0;
 }
 
 int
-JACKAudioBackend::pause ()
+JACKAudioBackend::set_sample_rate (float sr)
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       
+       if (!connected()) {
+               _target_sample_rate = sr;
+               return 0;
+       }
 
-       if (_priv_jack) {
-               jack_deactivate (_priv_jack);
+       if (sr == jack_get_sample_rate (_priv_jack)) {
+                return 0;
        }
 
-       return 0;
+       return -1;
 }
 
 int
-JACKAudioBackend::freewheel (bool onoff)
+JACKAudioBackend::set_buffer_size (uint32_t nframes)
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
 
-       if (onoff == _freewheeling) {
-               /* already doing what has been asked for */
-               
+       if (!connected()) {
+               _target_buffer_size = nframes;
                return 0;
        }
 
-       return jack_set_freewheel (_priv_jack, onoff);
+       if (nframes == jack_get_buffer_size (_priv_jack)) {
+                return 0;
+       }
+
+       return jack_set_buffer_size (_priv_jack, nframes);
 }
 
 int
-JACKAudioBackend::set_parameters (const Parameters& params)
+JACKAudioBackend::set_sample_format (SampleFormat sf)
 {
-       return 0;
+       /* as far as JACK clients are concerned, the hardware is always
+        * floating point format.
+        */
+       if (sf == FormatFloat) {
+               return 0;
+       }
+       return -1;
 }
 
-int 
-JACKAudioBackend::get_parameters (Parameters& params) const
+int
+JACKAudioBackend::set_interleaved (bool yn)
 {
-       return 0;
+       /* as far as JACK clients are concerned, the hardware is always
+        * non-interleaved
+        */
+       if (!yn) {
+               return 0;
+       }
+       return -1;
 }
 
-/*--- private support methods ---*/
-
 int
-JACKAudioBackend::connect_to_jack (string client_name, string session_uuid)
+JACKAudioBackend::set_input_channels (uint32_t cnt)
 {
-        EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
-        boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
-       jack_status_t status;
+       if (connected()) {
+               return -1;
+       }
 
-        /* revert all environment settings back to whatever they were when ardour started
-         */
+       _target_input_channels = cnt;
+       
+       return 0;
+}
 
-        if (global_epa) {
-                current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
-                global_epa->restore ();
-        }
+int
+JACKAudioBackend::set_output_channels (uint32_t cnt)
+{
+       if (connected()) {
+               return -1;
+       }
 
-       jack_client_name = client_name; /* might be reset below */
-#ifdef HAVE_JACK_SESSION
-       if (!session_uuid.empty())
-           _jack = jack_client_open (jack_client_name.c_str(), JackSessionID, &status, session_uuid.c_str());
-       else
-#endif
-       _jack = jack_client_open (jack_client_name.c_str(), JackNullOption, &status, 0);
+       _target_output_channels = cnt;
+
+       return 0;
+}
 
-       if (_jack == NULL) {
-               // error message is not useful here
+int
+JACKAudioBackend::set_systemic_input_latency (uint32_t l)
+{
+       if (connected()) {
                return -1;
        }
 
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
+       _target_systemic_input_latency = l;
 
-       if (status & JackNameNotUnique) {
-               jack_client_name = jack_get_client_name (_priv_jack);
+       return 0;
+}
+
+int
+JACKAudioBackend::set_systemic_output_latency (uint32_t l)
+{
+       if (connected()) {
+               return -1;
        }
 
+       _target_systemic_output_latency = l;
+
        return 0;
 }
 
-int
-JACKAudioBackend::disconnect_from_jack ()
+/* --- Parameter retrieval --- */
+
+std::string
+JACKAudioBackend::device_name () const
 {
+       return string();
+}
 
-int
-JACKAudioBackend::reconnect_to_jack ()
+float
+JACKAudioBackend::sample_rate () const
 {
-       if (_running) {
-               disconnect_from_jack ();
-               /* XXX give jackd a chance */
-               Glib::usleep (250000);
+       if (connected()) {
+               return _current_sample_rate;
        }
+       return _target_sample_rate;
+}
 
-       if (connect_to_jack (jack_client_name, "")) {
-               error << _("failed to connect to JACK") << endmsg;
-               return -1;
+uint32_t
+JACKAudioBackend::buffer_size () const
+{
+       if (connected()) {
+               return _current_buffer_size;
        }
+       return _target_buffer_size;
+}
 
-       Ports::iterator i;
+SampleFormat
+JACKAudioBackend::sample_format () const
+{
+       return FormatFloat;
+}
 
-       boost::shared_ptr<Ports> p = ports.reader ();
+bool
+JACKAudioBackend::interleaved () const
+{
+       return false;
+}
 
-       for (i = p->begin(); i != p->end(); ++i) {
-               if (i->second->reestablish ()) {
-                       break;
-               }
-       }
+uint32_t
+JACKAudioBackend::input_channels () const
+{
+       if (connected()) {
+               return n_physical (JackPortIsInput).n_audio();
+       } 
+       return _target_input_channels;
+}
 
-       if (i != p->end()) {
-               /* failed */
-               remove_all_ports ();
-               return -1;
-       }
+uint32_t
+JACKAudioBackend::output_channels () const
+{
+       if (connected()) {
+               return n_physical (JackPortIsOutput).n_audio();
+       } 
+       return _target_output_channels;
+}
 
-       GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
+uint32_t
+JACKAudioBackend::systemic_input_latency () const
+{
+       return _current_systemic_output_latency;
+}
+
+uint32_t
+JACKAudioBackend::systemic_output_latency () const
+{
+       return _current_systemic_output_latency;
+}
 
-       MIDI::Manager::instance()->reestablish (_priv_jack);
+size_t 
+JACKAudioBackend::raw_buffer_size(DataType t)
+{
+       std::map<DataType,size_t>::const_iterator s = _raw_buffer_sizes.find(t);
+       return (s != _raw_buffer_sizes.end()) ? s->second : 0;
+}
 
-       if (_session) {
-               _session->reset_jack_connection (_priv_jack);
-                jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
-               _session->set_frame_rate (jack_get_sample_rate (_priv_jack));
-       }
+/* ---- BASIC STATE CONTROL API: start/stop/pause/freewheel --- */
 
-       last_monitor_check = 0;
+int
+JACKAudioBackend::start ()
+{
+       if (!connected()) {
+               _jack_connection->open ();
+       }
 
-        set_jack_callbacks ();
+       engine.reestablish_ports ();
+       
+       if (!jack_port_type_get_buffer_size) {
+               warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg;
+       }
+       
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
 
+       engine.sample_rate_change (jack_get_sample_rate (_priv_jack));
+       
+       /* testing the nullity of this function name is a proxy for
+        * whether jack_activate() will definitely call the buffer size
+        * callback. with older versions of JACK, this function symbol
+        * will be null.  this is sort of reliable, but not clean since
+        * weak symbol support is highly platform and compiler
+        * specific.
+        */
+       if (!jack_port_type_get_buffer_size) {
+               jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
+       }
+       
+       set_jack_callbacks ();
+       
        if (jack_activate (_priv_jack) == 0) {
                _running = true;
-               _has_run = true;
        } else {
-               return -1;
+               // error << _("cannot activate JACK client") << endmsg;
        }
+       
+       engine.reconnect_ports ();
 
-       /* re-establish connections */
+       return 0;
+}
 
-       for (i = p->begin(); i != p->end(); ++i) {
-               i->second->reconnect ();
-       }
+int
+JACKAudioBackend::stop ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       
+       _jack_connection->close ();
 
-       MIDI::Manager::instance()->reconnect ();
+       _current_buffer_size = 0;
+       _current_sample_rate = 0;
 
-       Running (); /* EMIT SIGNAL*/
+       _raw_buffer_sizes.clear();
 
-       start_metering_thread ();
+       return 0;
+}
+
+int
+JACKAudioBackend::pause ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+       if (_priv_jack) {
+               jack_deactivate (_priv_jack);
+       }
 
        return 0;
 }
 
 int
-JACKAudioBackend::request_buffer_size (pframes_t nframes)
+JACKAudioBackend::freewheel (bool onoff)
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
 
-       if (nframes == jack_get_buffer_size (_priv_jack)) {
-                return 0;
+       if (onoff == _freewheeling) {
+               /* already doing what has been asked for */
+               
+               return 0;
        }
 
-       return jack_set_buffer_size (_priv_jack, nframes);
+       if (jack_set_freewheel (_priv_jack, onoff) == 0) {
+               _freewheeling = true;
+               return 0;
+       }
+
+       return -1;
 }
 
 /* --- TRANSPORT STATE MANAGEMENT --- */
@@ -196,35 +444,35 @@ JACKAudioBackend::request_buffer_size (pframes_t nframes)
 void
 JACKAudioBackend::transport_stop ()
 {
-       GET_PRIVATE_JACK_POINTER (_jack);
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
        jack_transport_stop (_priv_jack);
 }
 
 void
 JACKAudioBackend::transport_start ()
 {
-       GET_PRIVATE_JACK_POINTER (_jack);
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
        jack_transport_start (_priv_jack);
 }
 
 void
 JACKAudioBackend::transport_locate (framepos_t where)
 {
-       GET_PRIVATE_JACK_POINTER (_jack);
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
        jack_transport_locate (_priv_jack, where);
 }
 
 framepos_t 
 JACKAudioBackend::transport_frame () const 
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
        return jack_get_current_transport_frame (_priv_jack);
 }
 
-JACKAudioBackend::TransportState
-JACKAudioBackend::transport_state ()
+TransportState
+JACKAudioBackend::transport_state () const
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, ((TransportState) JackTransportStopped));
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, ((TransportState) JackTransportStopped));
        jack_position_t pos;
        return (TransportState) jack_transport_query (_priv_jack, &pos);
 }
@@ -232,30 +480,23 @@ JACKAudioBackend::transport_state ()
 int
 JACKAudioBackend::set_time_master (bool yn)
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
        if (yn) {
                return jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
        } else {
-               return jack_release_timebase (_jack);
+               return jack_release_timebase (_priv_jack);
        }
 }
 
 /* process-time */
 
-framecnt_t frame_rate () const;
-pframes_t frames_per_cycle () const;
-
-size_t raw_buffer_size(DataType t);
-
-int usecs_per_cycle () const { return _usecs_per_cycle; }
-
 bool
 JACKAudioBackend::get_sync_offset (pframes_t& offset) const
 {
 
 #ifdef HAVE_JACK_VIDEO_SUPPORT
 
-       GET_PRIVATE_JACK_POINTER_RET (_jack, false);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
 
        jack_position_t pos;
 
@@ -276,33 +517,24 @@ JACKAudioBackend::get_sync_offset (pframes_t& offset) const
 }
 
 pframes_t
-JACKAudioBackend::frames_since_cycle_start ()
+JACKAudioBackend::sample_time ()
 {
-       jack_client_t* _priv_jack = _jack;
-       if (!_running || !_priv_jack) {
-               return 0;
-       }
-       return jack_frames_since_cycle_start (_priv_jack);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_frame_time (_priv_jack);
 }
 
 pframes_t
-JACKAudioBackend::frame_time ()
+JACKAudioBackend::sample_time_at_cycle_start ()
 {
-       jack_client_t* _priv_jack = _jack;
-       if (!_running || !_priv_jack) {
-               return 0;
-       }
-       return jack_frame_time (_priv_jack);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_last_frame_time (_priv_jack);
 }
 
 pframes_t
-JACKAudioBackend::frame_time_at_cycle_start ()
+JACKAudioBackend::samples_since_cycle_start ()
 {
-       jack_client_t* _priv_jack = _jack;
-       if (!_running || !_priv_jack) {
-               return 0;
-       }
-       return jack_last_frame_time (_priv_jack);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_frames_since_cycle_start (_priv_jack);
 }
 
 /* JACK Callbacks */
@@ -316,29 +548,17 @@ ardour_jack_error (const char* msg)
 void
 JACKAudioBackend::set_jack_callbacks ()
 {
-       GET_PRIVATE_JACK_POINTER (_jack);
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
 
-        if (jack_on_info_shutdown) {
-                jack_on_info_shutdown (_priv_jack, halted_info, this);
-        } else {
-                jack_on_shutdown (_priv_jack, halted, this);
-        }
+        jack_set_thread_init_callback (_priv_jack, AudioEngine::thread_init_callback, 0);
 
-        jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this);
         jack_set_process_thread (_priv_jack, _process_thread, this);
         jack_set_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
         jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
-        jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this);
-        jack_set_port_registration_callback (_priv_jack, _registration_callback, this);
-        jack_set_port_connect_callback (_priv_jack, _connect_callback, this);
         jack_set_xrun_callback (_priv_jack, _xrun_callback, this);
         jack_set_sync_callback (_priv_jack, _jack_sync_callback, this);
         jack_set_freewheel_callback (_priv_jack, _freewheel_callback, this);
 
-        if (_session && _session->config.get_jack_time_master()) {
-                jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
-        }
-
 #ifdef HAVE_JACK_SESSION
         if( jack_set_session_callback)
                 jack_set_session_callback (_priv_jack, _session_callback, this);
@@ -355,40 +575,75 @@ void
 JACKAudioBackend::_jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
                                      jack_position_t* pos, int new_position, void *arg)
 {
-       static_cast<AudioEngine*> (arg)->jack_timebase_callback (state, nframes, pos, new_position);
+       static_cast<JACKAudioBackend*> (arg)->jack_timebase_callback (state, nframes, pos, new_position);
 }
 
 void
-JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
-                                    jack_position_t* pos, int new_position)
+JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_t /*nframes*/,
+                                         jack_position_t* pos, int /*new_position*/)
 {
-       if (_jack && _session && _session->synced_to_jack()) {
-               _session->jack_timebase_callback (state, nframes, pos, new_position);
+       TransportState tstate;
+       framepos_t position;
+
+       switch (state) {
+       case JackTransportStopped:
+               tstate = TransportStopped;
+               break;
+       case JackTransportRolling:
+               tstate = TransportRolling;
+               break;
+       case JackTransportLooping:
+               tstate = TransportLooping;
+               break;
+       case JackTransportStarting:
+               tstate = TransportStarting;
+               break;
+       }
+
+       if (pos) {
+               position = pos->frame;
        }
+
+       // engine.timebase_callback (tstate, nframes, position, new_position);
 }
 
 int
 JACKAudioBackend::_jack_sync_callback (jack_transport_state_t state, jack_position_t* pos, void* arg)
 {
-       return static_cast<AudioEngine*> (arg)->jack_sync_callback (state, pos);
+       return static_cast<JACKAudioBackend*> (arg)->jack_sync_callback (state, pos);
 }
 
 int
 JACKAudioBackend::jack_sync_callback (jack_transport_state_t state, jack_position_t* pos)
 {
-       if (_jack && _session) {
-               return _session->jack_sync_callback (state, pos);
+       TransportState tstate;
+
+       switch (state) {
+       case JackTransportStopped:
+               tstate = TransportStopped;
+               break;
+       case JackTransportRolling:
+               tstate = TransportRolling;
+               break;
+       case JackTransportLooping:
+               tstate = TransportLooping;
+               break;
+       case JackTransportStarting:
+               tstate = TransportStarting;
+               break;
        }
 
+       return engine.sync_callback (tstate, pos->frame);
+
        return true;
 }
 
 int
 JACKAudioBackend::_xrun_callback (void *arg)
 {
-       AudioEngine* ae = static_cast<AudioEngine*> (arg);
+       JACKAudioBackend* ae = static_cast<JACKAudioBackend*> (arg);
        if (ae->connected()) {
-               ae->Xrun (); /* EMIT SIGNAL */
+               ae->engine.Xrun (); /* EMIT SIGNAL */
        }
        return 0;
 }
@@ -397,106 +652,36 @@ JACKAudioBackend::_xrun_callback (void *arg)
 void
 JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg)
 {
-       AudioEngine* ae = static_cast<AudioEngine*> (arg);
+       JACKAudioBackend* ae = static_cast<JACKAudioBackend*> (arg);
        if (ae->connected()) {
-               ae->JackSessionEvent ( event ); /* EMIT SIGNAL */
+               ae->engine.JackSessionEvent (event); /* EMIT SIGNAL */
        }
 }
 #endif
 
-int
-JACKAudioBackend::_graph_order_callback (void *arg)
-{
-       AudioEngine* ae = static_cast<AudioEngine*> (arg);
-
-       if (ae->connected() && !ae->port_remove_in_progress) {
-               ae->GraphReordered (); /* EMIT SIGNAL */
-       }
-       
-       return 0;
-}
-
 void
 JACKAudioBackend::_freewheel_callback (int onoff, void *arg)
 {
-       static_cast<AudioEngine*>(arg)->freewheel_callback (onoff);
+       static_cast<JACKAudioBackend*>(arg)->freewheel_callback (onoff);
 }
 
 void
 JACKAudioBackend::freewheel_callback (int onoff)
 {
        _freewheeling = onoff;
-
-       if (onoff) {
-               _pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
-               MIDI::Manager::instance()->mmc()->enable_send (false);
-       } else {
-               MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled);
-       }
-}
-
-void
-JACKAudioBackend::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg)
-{
-       AudioEngine* ae = static_cast<AudioEngine*> (arg);
-
-       if (!ae->port_remove_in_progress) {
-               ae->PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
-       }
+       engine.freewheel_callback (onoff);
 }
 
 void
 JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* arg)
 {
-       return static_cast<AudioEngine *> (arg)->jack_latency_callback (mode);
-}
-
-void
-JACKAudioBackend::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg)
-{
-       AudioEngine* ae = static_cast<AudioEngine*> (arg);
-       ae->connect_callback (id_a, id_b, conn);
-}
-
-void
-JACKAudioBackend::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn)
-{
-       if (port_remove_in_progress) {
-               return;
-       }
-
-       GET_PRIVATE_JACK_POINTER (_jack);
-
-       jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a);
-       jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b);
-
-       boost::shared_ptr<Port> port_a;
-       boost::shared_ptr<Port> port_b;
-       Ports::iterator x;
-       boost::shared_ptr<Ports> pr = ports.reader ();
-
-
-       x = pr->find (make_port_name_relative (jack_port_name (jack_port_a)));
-       if (x != pr->end()) {
-               port_a = x->second;
-       }
-
-       x = pr->find (make_port_name_relative (jack_port_name (jack_port_b)));
-       if (x != pr->end()) {
-               port_b = x->second;
-       }
-
-       PortConnectedOrDisconnected (
-               port_a, jack_port_name (jack_port_a),
-               port_b, jack_port_name (jack_port_b),
-               conn == 0 ? false : true
-               ); /* EMIT SIGNAL */
+       return static_cast<JACKAudioBackend*> (arg)->jack_latency_callback (mode);
 }
 
 int
 JACKAudioBackend::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
 {
-        GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
+        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
         ThreadData* td = new ThreadData (this, f, stacksize);
 
         if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
@@ -522,7 +707,7 @@ JACKAudioBackend::_start_process_thread (void* arg)
 void*
 JACKAudioBackend::_process_thread (void *arg)
 {
-       return static_cast<AudioEngine *> (arg)->process_thread ();
+       return static_cast<JACKAudioBackend*> (arg)->process_thread ();
 }
 
 void*
@@ -531,16 +716,14 @@ JACKAudioBackend::process_thread ()
         /* JACK doesn't do this for us when we use the wait API
          */
 
-        _thread_init_callback (0);
-
-        _main_thread = new ProcessThread;
+        AudioEngine::thread_init_callback (this);
 
         while (1) {
-                GET_PRIVATE_JACK_POINTER_RET(_jack,0);
+                GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
 
                 pframes_t nframes = jack_cycle_wait (_priv_jack);
-
-                if (process_callback (nframes)) {
+               
+                if (engine.process_callback (nframes)) {
                         return 0;
                 }
 
@@ -553,41 +736,26 @@ JACKAudioBackend::process_thread ()
 int
 JACKAudioBackend::_sample_rate_callback (pframes_t nframes, void *arg)
 {
-       return static_cast<AudioEngine *> (arg)->jack_sample_rate_callback (nframes);
+       return static_cast<JACKAudioBackend*> (arg)->jack_sample_rate_callback (nframes);
 }
 
 int
 JACKAudioBackend::jack_sample_rate_callback (pframes_t nframes)
 {
-       _frame_rate = nframes;
-       _usecs_per_cycle = (int) floor ((((double) frames_per_cycle() / nframes)) * 1000000.0);
-
-       /* check for monitor input change every 1/10th of second */
-
-       monitor_check_interval = nframes / 10;
-       last_monitor_check = 0;
-
-       if (_session) {
-               _session->set_frame_rate (nframes);
-       }
-
-       SampleRateChanged (nframes); /* EMIT SIGNAL */
-
-       return 0;
+       _current_sample_rate = nframes;
+       return engine.sample_rate_change (nframes);
 }
 
 void
 JACKAudioBackend::jack_latency_callback (jack_latency_callback_mode_t mode)
 {
-        if (_session) {
-                _session->update_latency (mode == JackPlaybackLatency);
-        }
+       engine.latency_callback (mode == JackPlaybackLatency);
 }
 
 int
 JACKAudioBackend::_bufsize_callback (pframes_t nframes, void *arg)
 {
-       return static_cast<AudioEngine *> (arg)->jack_bufsize_callback (nframes);
+       return static_cast<JACKAudioBackend*> (arg)->jack_bufsize_callback (nframes);
 }
 
 int
@@ -595,15 +763,14 @@ JACKAudioBackend::jack_bufsize_callback (pframes_t nframes)
 {
         /* if the size has not changed, this should be a no-op */
 
-        if (nframes == _buffer_size) {
+        if (nframes == _current_buffer_size) {
                 return 0;
         }
 
-       GET_PRIVATE_JACK_POINTER_RET (_jack, 1);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 1);
 
-       _buffer_size = nframes;
-       _usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0);
-       last_monitor_check = 0;
+       _current_buffer_size = nframes;
+       _current_usecs_per_cycle = (int) floor ((((double) nframes / sample_rate())) * 1000000.0);
 
         if (jack_port_type_get_buffer_size) {
                 _raw_buffer_sizes[DataType::AUDIO] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_AUDIO_TYPE);
@@ -625,74 +792,36 @@ JACKAudioBackend::jack_bufsize_callback (pframes_t nframes)
                 _raw_buffer_sizes[DataType::MIDI] = nframes * 4 - (nframes/2);
         }
 
-       {
-               Glib::Threads::Mutex::Lock lm (_process_lock);
-
-               boost::shared_ptr<Ports> p = ports.reader();
-
-               for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-                       i->second->reset();
-               }
-       }
-
-       if (_session) {
-               _session->set_block_size (_buffer_size);
-       }
+       engine.buffer_size_change (nframes);
 
        return 0;
 }
 
 void
-JACKAudioBackend::halted_info (jack_status_t code, const char* reason, void *arg)
+JACKAudioBackend::disconnected (const char* why)
 {
         /* called from jack shutdown handler  */
 
-        AudioEngine* ae = static_cast<AudioEngine *> (arg);
-        bool was_running = ae->_running;
+       bool was_running = _running;
 
-        ae->stop_metering_thread ();
-
-        ae->_running = false;
-        ae->_buffer_size = 0;
-        ae->_frame_rate = 0;
-        ae->_jack = 0;
+        _running = false;
+        _current_buffer_size = 0;
+        _current_sample_rate = 0;
 
         if (was_running) {
-               MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
-#ifdef HAVE_JACK_ON_INFO_SHUTDOWN
-                switch (code) {
-                case JackBackendError:
-                        ae->Halted(reason); /* EMIT SIGNAL */
-                        break;
-                default:
-                        ae->Halted(""); /* EMIT SIGNAL */
-                }
-#else
-                ae->Halted(""); /* EMIT SIGNAL */
-#endif
+               engine.halted_callback (why); /* EMIT SIGNAL */
         }
 }
+float 
+JACKAudioBackend::cpu_load() const 
+{
+       GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
+       return jack_cpu_load (_priv_jack);
+}
 
 void
-JACKAudioBackend::halted (void *arg)
+JACKAudioBackend::update_latencies ()
 {
-        cerr << "HALTED by JACK\n";
-
-        /* called from jack shutdown handler  */
-
-       AudioEngine* ae = static_cast<AudioEngine *> (arg);
-       bool was_running = ae->_running;
-
-       ae->stop_metering_thread ();
-
-       ae->_running = false;
-       ae->_buffer_size = 0;
-       ae->_frame_rate = 0;
-        ae->_jack = 0;
-
-       if (was_running) {
-               MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
-               ae->Halted(""); /* EMIT SIGNAL */
-       }
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       jack_recompute_total_latencies (_priv_jack);
 }
-