#include "ardour/filesystem_paths.h"
#include "ardour/port_manager.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
#include "audio_utils.h"
, _pcmio (0)
, _run (false)
, _active (false)
+ , _use_blocking_api(false)
, _freewheel (false)
, _freewheeling (false)
, _freewheel_ack (false)
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
{
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
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
{
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)
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) {
_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;
}
_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;
_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;
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) {
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
{
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);
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());
static bool available ();
static ARDOUR::AudioBackendInfo _descriptor = {
- "PortAudio",
+ BACKEND_NAME,
instantiate,
deinstantiate,
backend_factory,