enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / backends / portaudio / portaudio_backend.cc
index e6ba728cb1d5a15affc38dfbcb07fc00e725ac83..b25a54f7a9e965e375fa92a2b509e04791bf3c7e 100644 (file)
@@ -41,7 +41,7 @@
 
 #include "ardour/filesystem_paths.h"
 #include "ardour/port_manager.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 #include "audio_utils.h"
 
@@ -66,6 +66,7 @@ PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info)
        , _pcmio (0)
        , _run (false)
        , _active (false)
+       , _use_blocking_api(false)
        , _freewheel (false)
        , _freewheeling (false)
        , _freewheel_ack (false)
@@ -156,9 +157,22 @@ PortAudioBackend::set_driver (const std::string& name)
 bool
 PortAudioBackend::update_devices ()
 {
+       // update midi device info?
        return _pcmio->update_devices();
 }
 
+void
+PortAudioBackend::set_use_buffered_io (bool use_buffered_io)
+{
+       DEBUG_AUDIO (string_compose ("Portaudio: use_buffered_io %1 \n", use_buffered_io));
+
+       if (running()) {
+               return;
+       }
+
+       _use_blocking_api = use_buffered_io;
+}
+
 std::string
 PortAudioBackend::driver_name () const
 {
@@ -329,6 +343,24 @@ PortAudioBackend::set_systemic_output_latency (uint32_t sl)
        return 0;
 }
 
+int
+PortAudioBackend::set_systemic_midi_input_latency (std::string const device, uint32_t sl)
+{
+       MidiDeviceInfo* nfo = midi_device_info (device);
+       if (!nfo) return -1;
+       nfo->systemic_input_latency = sl;
+       return 0;
+}
+
+int
+PortAudioBackend::set_systemic_midi_output_latency (std::string const device, uint32_t sl)
+{
+       MidiDeviceInfo* nfo = midi_device_info (device);
+       if (!nfo) return -1;
+       nfo->systemic_output_latency = sl;
+       return 0;
+}
+
 /* Retrieving parameters */
 std::string
 PortAudioBackend::device_name () const
@@ -390,6 +422,22 @@ PortAudioBackend::systemic_output_latency () const
        return _systemic_audio_output_latency;
 }
 
+uint32_t
+PortAudioBackend::systemic_midi_input_latency (std::string const device) const
+{
+       MidiDeviceInfo* nfo = midi_device_info (device);
+       if (!nfo) return 0;
+       return nfo->systemic_input_latency;
+}
+
+uint32_t
+PortAudioBackend::systemic_midi_output_latency (std::string const device) const
+{
+       MidiDeviceInfo* nfo = midi_device_info (device);
+       if (!nfo) return 0;
+       return nfo->systemic_output_latency;
+}
+
 std::string
 PortAudioBackend::control_app_name () const
 {
@@ -431,6 +479,61 @@ PortAudioBackend::midi_option () const
        return _midi_driver_option;
 }
 
+std::vector<AudioBackend::DeviceStatus>
+PortAudioBackend::enumerate_midi_devices () const
+{
+       std::vector<AudioBackend::DeviceStatus> midi_device_status;
+       std::vector<MidiDeviceInfo*> device_info;
+
+       if (_midi_driver_option == winmme_driver_name) {
+               _midiio->update_device_info ();
+               device_info = _midiio->get_device_info ();
+       }
+
+       for (std::vector<MidiDeviceInfo*>::const_iterator i = device_info.begin();
+            i != device_info.end();
+            ++i) {
+               midi_device_status.push_back(DeviceStatus((*i)->device_name, true));
+       }
+       return midi_device_status;
+}
+
+MidiDeviceInfo*
+PortAudioBackend::midi_device_info (const std::string& device_name) const
+{
+       std::vector<MidiDeviceInfo*> dev_info;
+
+       if (_midi_driver_option == winmme_driver_name) {
+               dev_info = _midiio->get_device_info();
+
+               for (std::vector<MidiDeviceInfo*>::const_iterator i = dev_info.begin();
+                    i != dev_info.end();
+                    ++i) {
+                       if ((*i)->device_name == device_name) {
+                               return *i;
+                       }
+               }
+       }
+       return 0;
+}
+
+int
+PortAudioBackend::set_midi_device_enabled (std::string const device, bool enable)
+{
+       MidiDeviceInfo* nfo = midi_device_info(device);
+       if (!nfo) return -1;
+       nfo->enable = enable;
+       return 0;
+}
+
+bool
+PortAudioBackend::midi_device_enabled (std::string const device) const
+{
+       MidiDeviceInfo* nfo = midi_device_info(device);
+       if (!nfo) return false;
+       return nfo->enable;
+}
+
 /* State Control */
 
 static void * blocking_thread_func (void *arg)
@@ -482,21 +585,21 @@ PortAudioBackend::_start (bool for_latency_measurement)
 
        PaErrorCode err = paNoError;
 
-#ifdef USE_BLOCKING_API
-       err = _pcmio->open_blocking_stream(name_to_id(_input_audio_device),
-                                          name_to_id(_output_audio_device),
-                                          _samplerate,
-                                          _samples_per_period);
-
-#else
-       err = _pcmio->open_callback_stream(name_to_id(_input_audio_device),
-                                          name_to_id(_output_audio_device),
-                                          _samplerate,
-                                          _samples_per_period,
-                                          portaudio_callback,
-                                          this);
-
-#endif
+       if (_use_blocking_api) {
+               DEBUG_AUDIO("Opening blocking audio stream\n");
+               err = _pcmio->open_blocking_stream(name_to_id(_input_audio_device),
+                                                  name_to_id(_output_audio_device),
+                                                  _samplerate,
+                                                  _samples_per_period);
+       } else {
+               DEBUG_AUDIO("Opening callback audio stream\n");
+               err = _pcmio->open_callback_stream(name_to_id(_input_audio_device),
+                                                  name_to_id(_output_audio_device),
+                                                  _samplerate,
+                                                  _samples_per_period,
+                                                  portaudio_callback,
+                                                  this);
+       }
 
        // reintepret Portaudio error messages
        switch (err) {
@@ -579,22 +682,22 @@ PortAudioBackend::_start (bool for_latency_measurement)
        _run = true;
        _port_change_flag = false;
 
-#ifdef USE_BLOCKING_API
-       if (!start_blocking_process_thread()) {
-               return ProcessThreadStartError;
-       }
-#else
-       if (_pcmio->start_stream() != paNoError) {
-               DEBUG_AUDIO("Unable to start stream\n");
-               return AudioDeviceOpenError;
-       }
+       if (_use_blocking_api) {
+               if (!start_blocking_process_thread()) {
+                       return ProcessThreadStartError;
+               }
+       } else {
+               if (_pcmio->start_stream() != paNoError) {
+                       DEBUG_AUDIO("Unable to start stream\n");
+                       return AudioDeviceOpenError;
+               }
 
-       if (!start_freewheel_process_thread()) {
-               DEBUG_AUDIO("Unable to start freewheel thread\n");
-               stop();
-               return ProcessThreadStartError;
+               if (!start_freewheel_process_thread()) {
+                       DEBUG_AUDIO("Unable to start freewheel thread\n");
+                       stop();
+                       return ProcessThreadStartError;
+               }
        }
-#endif
 
        return NoError;
 }
@@ -724,20 +827,19 @@ PortAudioBackend::stop ()
 
        _run = false;
 
-#ifdef USE_BLOCKING_API
-       if (!stop_blocking_process_thread ()) {
-               return -1;
-       }
-#else
-       _pcmio->close_stream ();
-       _active = false;
+       if (_use_blocking_api) {
+               if (!stop_blocking_process_thread()) {
+                       return -1;
+               }
+       } else {
+               _pcmio->close_stream();
+               _active = false;
 
-       if (!stop_freewheel_process_thread ()) {
-               return -1;
+               if (!stop_freewheel_process_thread()) {
+                       return -1;
+               }
        }
 
-#endif
-
        unregister_ports();
 
        return (_active == false) ? 0 : -1;
@@ -810,6 +912,7 @@ PortAudioBackend::freewheel_process_thread()
                                _reinit_thread_callback = true; // hand over _main_thread
                                _freewheel_ack = false; // prepare next handshake
                                _midiio->set_enabled(true);
+                               engine.freewheel_callback (_freewheeling);
                        } else {
                                first_run = true;
                                _freewheel = true;
@@ -1037,16 +1140,15 @@ PortAudioBackend::join_process_threads ()
 bool
 PortAudioBackend::in_process_thread ()
 {
-#ifdef USE_BLOCKING_API
-       if (pthread_equal (_main_blocking_thread, pthread_self()) != 0) {
-               return true;
-       }
-#else
-       if (pthread_equal (_main_thread, pthread_self()) != 0) {
-               return true;
+       if (_use_blocking_api) {
+               if (pthread_equal(_main_blocking_thread, pthread_self()) != 0) {
+                       return true;
+               }
+       } else {
+               if (pthread_equal(_main_thread, pthread_self()) != 0) {
+                       return true;
+               }
        }
-#endif
-
        for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
        {
                if (pthread_equal (*i, pthread_self ()) != 0) {
@@ -1136,6 +1238,24 @@ PortAudioBackend::get_port_property (PortHandle port,
        return -1;
 }
 
+int
+PortAudioBackend::set_port_property (PortHandle port,
+                                     const std::string& key,
+                                     const std::string& value,
+                                     const std::string& type)
+{
+       if (!valid_port (port)) {
+               DEBUG_PORTS("get_port_name: Invalid Port(s)\n");
+               return -1;
+       }
+
+       if (key == "http://jackaudio.org/metadata/pretty-name" && type.empty ()) {
+               static_cast<PamPort*>(port)->set_pretty_name (value);
+               return 0;
+       }
+       return -1;
+}
+
 PortEngine::PortHandle
 PortAudioBackend::get_port_by_name (const std::string& name) const
 {
@@ -1303,13 +1423,19 @@ PortAudioBackend::register_system_midi_ports()
        for (std::vector<WinMMEMidiInputDevice*>::const_iterator i = inputs.begin ();
             i != inputs.end ();
             ++i) {
-               std::string port_name = "system_midi:" + (*i)->name() + " capture";
+               std::string port_name = "system:midi_capture_" + (*i)->name();
                PortHandle p =
                    add_port (port_name,
                              DataType::MIDI,
                              static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
                if (!p) return -1;
+
+               MidiDeviceInfo* info = _midiio->get_device_info((*i)->name());
+               if (info) { // assert?
+                       lr.min = lr.max = _samples_per_period + info->systemic_input_latency;
+               }
                set_latency_range (p, false, lr);
+
                PortMidiPort* midi_port = static_cast<PortMidiPort*>(p);
                midi_port->set_pretty_name ((*i)->name());
                _system_midi_in.push_back (midi_port);
@@ -1321,13 +1447,19 @@ PortAudioBackend::register_system_midi_ports()
        for (std::vector<WinMMEMidiOutputDevice*>::const_iterator i = outputs.begin ();
             i != outputs.end ();
             ++i) {
-               std::string port_name = "system_midi:" + (*i)->name() + " playback";
+               std::string port_name = "system:midi_playback_" + (*i)->name();
                PortHandle p =
                    add_port (port_name,
                              DataType::MIDI,
                              static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
                if (!p) return -1;
+
+               MidiDeviceInfo* info = _midiio->get_device_info((*i)->name());
+               if (info) { // assert?
+                       lr.min = lr.max = _samples_per_period + info->systemic_output_latency;
+               }
                set_latency_range (p, false, lr);
+
                PortMidiPort* midi_port = static_cast<PortMidiPort*>(p);
                midi_port->set_n_periods(2);
                midi_port->set_pretty_name ((*i)->name());
@@ -2001,7 +2133,7 @@ static bool already_configured ();
 static bool available ();
 
 static ARDOUR::AudioBackendInfo _descriptor = {
-       "PortAudio",
+       BACKEND_NAME,
        instantiate,
        deinstantiate,
        backend_factory,