enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / backends / jack / jack_audiobackend.cc
index b60d2418c9868717e45638d245644dbb905c4330..8b9e4af1dda5926a62005795cbe741c092ffea2b 100644 (file)
@@ -27,9 +27,6 @@
 
 #include "pbd/error.h"
 
-#include "jack/jack.h"
-#include "jack/thread.h"
-
 #include "ardour/audioengine.h"
 #include "ardour/session.h"
 #include "ardour/types.h"
@@ -39,7 +36,7 @@
 #include "jack_utils.h"
 #include "jack_session.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace ARDOUR;
 using namespace PBD;
@@ -57,6 +54,7 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, AudioBackendInfo& info, boos
        , _freewheeling (false)
        , _target_sample_rate (48000)
        , _target_buffer_size (1024)
+       , _target_num_periods (2)
        , _target_interleaved (false)
        , _target_input_channels (0)
        , _target_output_channels (0)
@@ -75,7 +73,7 @@ JACKAudioBackend::~JACKAudioBackend()
 }
 
 string
-JACKAudioBackend::name() const 
+JACKAudioBackend::name() const
 {
        return X_("JACK");
 }
@@ -129,8 +127,8 @@ JACKAudioBackend::enumerate_devices () const
        if (all_devices.find (_target_driver) == all_devices.end()) {
                all_devices.insert (make_pair (_target_driver, std::set<string>()));
        }
-       
-       /* store every device we've found, by driver name. 
+
+       /* store every device we've found, by driver name.
         *
         * This is so we do not confuse ALSA, FFADO, netjack etc. devices
         * with each other.
@@ -141,7 +139,7 @@ JACKAudioBackend::enumerate_devices () const
        for (vector<string>::const_iterator d = currently_available.begin(); d != currently_available.end(); ++d) {
                all.insert (*d);
        }
-       
+
        for (DeviceList::const_iterator d = all.begin(); d != all.end(); ++d) {
                if (find (currently_available.begin(), currently_available.end(), *d) == currently_available.end()) {
                        statuses.push_back (DeviceStatus (*d, false));
@@ -149,7 +147,7 @@ JACKAudioBackend::enumerate_devices () const
                        statuses.push_back (DeviceStatus (*d, false));
                }
        }
-       
+
        return statuses;
 }
 
@@ -157,13 +155,13 @@ vector<float>
 JACKAudioBackend::available_sample_rates (const string& device) const
 {
        vector<float> f;
-       
+
        if (device == _target_device && available()) {
                f.push_back (sample_rate());
                return f;
        }
 
-       /* if JACK is not already running, just list a bunch of reasonable 
+       /* if JACK is not already running, just list a bunch of reasonable
           values and let the future sort it all out.
        */
 
@@ -177,7 +175,7 @@ JACKAudioBackend::available_sample_rates (const string& device) const
        f.push_back (96000.0);
        f.push_back (192000.0);
        f.push_back (384000.0);
-       
+
        return f;
 }
 
@@ -185,7 +183,7 @@ vector<uint32_t>
 JACKAudioBackend::available_buffer_sizes (const string& device) const
 {
        vector<uint32_t> s;
-               
+
        if (device == _target_device && available()) {
                s.push_back (buffer_size());
                return s;
@@ -206,6 +204,17 @@ JACKAudioBackend::available_buffer_sizes (const string& device) const
        return s;
 }
 
+std::vector<uint32_t>
+JACKAudioBackend::available_period_sizes (const std::string& driver) const
+{
+       vector<uint32_t> s;
+       if (ARDOUR::get_jack_audio_driver_supports_setting_period_count (driver)) {
+               s.push_back (2);
+               s.push_back (3);
+       }
+       return s;
+}
+
 uint32_t
 JACKAudioBackend::available_input_channel_count (const string& /*device*/) const
 {
@@ -249,6 +258,16 @@ JACKAudioBackend::set_sample_rate (float sr)
        return -1;
 }
 
+int
+JACKAudioBackend::set_peridod_size (uint32_t nperiods)
+{
+       if (!available()) {
+               _target_num_periods = nperiods;
+               return 0;
+       }
+       return -1;
+}
+
 int
 JACKAudioBackend::set_buffer_size (uint32_t nframes)
 {
@@ -289,7 +308,7 @@ JACKAudioBackend::set_input_channels (uint32_t cnt)
        }
 
        _target_input_channels = cnt;
-       
+
        return 0;
 }
 
@@ -342,7 +361,7 @@ JACKAudioBackend::device_name () const
        if (!_jack_connection->in_control()) {
                return "???"; // JACK has no way (as of fall 2013) to return
                              // the device name
-       } 
+       }
 
        return _target_device;
 }
@@ -365,7 +384,7 @@ JACKAudioBackend::sample_rate () const
                if (available()) {
                        return _current_sample_rate;
                } else {
-                       return 0;
+                       return _jack_connection->probed_sample_rate ();
                }
        }
        return _target_sample_rate;
@@ -378,12 +397,18 @@ JACKAudioBackend::buffer_size () const
                if (available()) {
                        return _current_buffer_size;
                } else {
-                       return 0;
+                       return _jack_connection->probed_buffer_size ();
                }
        }
        return _target_buffer_size;
 }
 
+uint32_t
+JACKAudioBackend::period_size () const
+{
+       return _target_num_periods;
+}
+
 bool
 JACKAudioBackend::interleaved () const
 {
@@ -444,7 +469,7 @@ JACKAudioBackend::systemic_output_latency () const
        return _target_systemic_output_latency;
 }
 
-size_t 
+size_t
 JACKAudioBackend::raw_buffer_size(DataType t)
 {
        std::map<DataType,size_t>::const_iterator s = _raw_buffer_sizes.find(t);
@@ -464,11 +489,16 @@ JACKAudioBackend::setup_jack_startup_command (bool for_latency_measurement)
        options.driver = _target_driver;
        options.samplerate = _target_sample_rate;
        options.period_size = _target_buffer_size;
-       options.num_periods = 2;
+       options.num_periods = _target_num_periods;
        options.input_device = _target_device;
        options.output_device = _target_device;
-       options.input_latency = _target_systemic_input_latency;
-       options.output_latency = _target_systemic_output_latency;
+       if (for_latency_measurement) {
+               options.input_latency = 0;
+               options.output_latency = 0;
+       } else {
+               options.input_latency = _target_systemic_input_latency;
+               options.output_latency = _target_systemic_output_latency;
+       }
        options.input_channels = _target_input_channels;
        options.output_channels = _target_output_channels;
        if (_target_sample_format == FormatInt16) {
@@ -476,7 +506,7 @@ JACKAudioBackend::setup_jack_startup_command (bool for_latency_measurement)
        }
        options.realtime = true;
        options.ports_max = 2048;
-       
+
        ARDOUR::set_midi_option (options, _target_midi_option);
 
        /* this must always be true for any server instance we start ourselves
@@ -486,7 +516,7 @@ JACKAudioBackend::setup_jack_startup_command (bool for_latency_measurement)
 
        string cmdline;
 
-       if (!get_jack_command_line_string (options, cmdline, for_latency_measurement)) {
+       if (!get_jack_command_line_string (options, cmdline)) {
                /* error, somehow - we will still try to start JACK
                 * automatically but it will be without our preferred options
                 */
@@ -507,7 +537,7 @@ JACKAudioBackend::_start (bool for_latency_measurement)
        if (!available()) {
 
                if (_jack_connection->in_control()) {
-                       /* we will be starting JACK, so set up the 
+                       /* we will be starting JACK, so set up the
                           command that JACK will use when it (auto-)starts
                        */
                        setup_jack_startup_command (for_latency_measurement);
@@ -517,15 +547,15 @@ JACKAudioBackend::_start (bool for_latency_measurement)
                        return -1;
                }
        }
-       
+
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
 
        /* get the buffer size and sample rates established */
 
        jack_sample_rate_callback (jack_get_sample_rate (_priv_jack));
        jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
-       
-       /* Now that we have buffer size and sample rate established, the engine 
+
+       /* Now that we have buffer size and sample rate established, the engine
           can go ahead and do its stuff
        */
 
@@ -537,9 +567,9 @@ JACKAudioBackend::_start (bool for_latency_measurement)
        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;
        }
-       
+
        set_jack_callbacks ();
-       
+
        if (jack_activate (_priv_jack) == 0) {
                _running = true;
        } else {
@@ -556,7 +586,7 @@ JACKAudioBackend::stop ()
 {
        _running = false; // no 'engine halted message'.
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       
+
        _jack_connection->close ();
 
        _current_buffer_size = 0;
@@ -574,7 +604,7 @@ JACKAudioBackend::freewheel (bool onoff)
 
        if (onoff == _freewheeling) {
                /* already doing what has been asked for */
-               
+
                return 0;
        }
 
@@ -609,8 +639,8 @@ JACKAudioBackend::transport_locate (framepos_t where)
        jack_transport_locate (_priv_jack, where);
 }
 
-framepos_t 
-JACKAudioBackend::transport_frame () const 
+framepos_t
+JACKAudioBackend::transport_frame () const
 {
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
        return jack_get_current_transport_frame (_priv_jack);
@@ -663,14 +693,14 @@ JACKAudioBackend::get_sync_offset (pframes_t& offset) const
        return false;
 }
 
-pframes_t
+framepos_t
 JACKAudioBackend::sample_time ()
 {
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
        return jack_frame_time (_priv_jack);
 }
 
-pframes_t
+framepos_t
 JACKAudioBackend::sample_time_at_cycle_start ()
 {
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
@@ -836,19 +866,20 @@ JACKAudioBackend::create_process_thread (boost::function<void()> f)
 int
 JACKAudioBackend::join_process_threads ()
 {
-        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-
        int ret = 0;
 
        for (std::vector<jack_native_thread_t>::const_iterator i = _jack_threads.begin ();
             i != _jack_threads.end(); i++) {
 
-#if defined(USING_JACK2_EXPANSION_OF_JACK_API) || defined(PLATFORM_WINDOWS)
-               if (jack_client_stop_thread (_priv_jack, *i) != 0) {
+#if defined(USING_JACK2_EXPANSION_OF_JACK_API) || defined __jack_systemdeps_h__
+               // jack_client is not used by JACK2's implementation
+               // also jack_client_close() leaves threads active
+               if (jack_client_stop_thread (NULL, *i) != 0)
 #else
                void* status;
-               if (pthread_join (*i, &status) != 0) {
+               if (pthread_join (*i, &status) != 0)
 #endif
+               {
                        error << "AudioEngine: cannot stop process thread" << endmsg;
                        ret += -1;
                }
@@ -862,10 +893,20 @@ JACKAudioBackend::join_process_threads ()
 bool
 JACKAudioBackend::in_process_thread ()
 {
+#if defined COMPILER_MINGW && (!defined PTW32_VERSION || defined __jack_systemdeps_h__)
+       if (_main_thread == GetCurrentThread()) {
+               return true;
+       }
+#else // pthreads
+       if (pthread_equal (_main_thread, pthread_self()) != 0) {
+               return true;
+       }
+#endif
+
        for (std::vector<jack_native_thread_t>::const_iterator i = _jack_threads.begin ();
             i != _jack_threads.end(); i++) {
 
-#ifdef COMPILER_MINGW
+#if defined COMPILER_MINGW && (!defined PTW32_VERSION || defined __jack_systemdeps_h__)
                if (*i == GetCurrentThread()) {
                        return true;
                }
@@ -909,13 +950,20 @@ JACKAudioBackend::process_thread ()
         /* JACK doesn't do this for us when we use the wait API
          */
 
+#if defined COMPILER_MINGW && (!defined PTW32_VERSION || defined __jack_systemdeps_h__)
+       _main_thread = GetCurrentThread();
+#else
+       _main_thread = pthread_self ();
+#endif
+
+
         AudioEngine::thread_init_callback (this);
 
         while (1) {
                 GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
 
                 pframes_t nframes = jack_cycle_wait (_priv_jack);
-               
+
                 if (engine.process_callback (nframes)) {
                         return 0;
                 }
@@ -1003,8 +1051,8 @@ JACKAudioBackend::disconnected (const char* why)
         }
 }
 
-float 
-JACKAudioBackend::dsp_load() const 
+float
+JACKAudioBackend::dsp_load() const
 {
        GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
        return jack_cpu_load (_priv_jack);
@@ -1035,7 +1083,7 @@ JACKAudioBackend::n_physical (unsigned long flags) const
                                }
                        }
                }
-               
+
                jack_free (ports);
        }
 
@@ -1069,9 +1117,9 @@ JACKAudioBackend::control_app_name () const
                if (_target_driver.empty() || _target_device.empty()) {
                        return appname;
                }
-               
+
                if (_target_driver == "ALSA") {
-                       
+
                        if (_target_device == "Hammerfall DSP") {
                                appname = "hdspconf";
                        } else if (_target_device == "M Audio Delta 1010") {
@@ -1122,7 +1170,7 @@ JACKAudioBackend::speed_and_position (double& speed, framepos_t& position)
        jack_transport_state_t state;
        bool starting;
 
-       /* this won't be called if the port engine in use is not JACK, so we do 
+       /* this won't be called if the port engine in use is not JACK, so we do
           not have to worry about the type of PortEngine::private_handle()
        */
 
@@ -1158,3 +1206,11 @@ JACKAudioBackend::speed_and_position (double& speed, framepos_t& position)
        position = pos.frame;
        return starting;
 }
+
+int
+JACKAudioBackend::reset_device ()
+{
+        /* XXX need to figure out what this means for JACK
+         */
+        return 0;
+}