X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fbackends%2Falsa%2Falsa_audiobackend.cc;h=725fc80b765c63b9f64340c2afaa3229ec07d72b;hb=dac57703ccd7205ac94c14b407b802a69f4187f1;hp=ab6c029c5972126ceef35ec48f23f34034d3a040;hpb=dc2030cfd7656d8f502a31fce19b49df5df10eb7;p=ardour.git diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc index ab6c029c59..725fc80b76 100644 --- a/libs/backends/alsa/alsa_audiobackend.cc +++ b/libs/backends/alsa/alsa_audiobackend.cc @@ -44,6 +44,9 @@ std::vector AlsaAudioBackend::_output_audio_device_s std::vector AlsaAudioBackend::_duplex_audio_device_status; std::vector AlsaAudioBackend::_midi_device_status; +ALSADeviceInfo AlsaAudioBackend::_input_audio_device_info; +ALSADeviceInfo AlsaAudioBackend::_output_audio_device_info; + AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info) : AudioBackend (e, info) , _pcmi (0) @@ -55,7 +58,7 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info) , _last_process_start (0) , _input_audio_device("") , _output_audio_device("") - , _midi_driver_option(_("None")) + , _midi_driver_option(get_standard_device_name(DeviceNone)) , _device_reservation(0) , _samplerate (48000) , _samples_per_period (1024) @@ -66,10 +69,14 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info) , _systemic_audio_output_latency (0) , _dsp_load (0) , _processed_samples (0) + , _midi_ins (0) + , _midi_outs (0) , _port_change_flag (false) { _instance_name = s_instance_name; pthread_mutex_init (&_port_callback_mutex, 0); + _input_audio_device_info.valid = false; + _output_audio_device_info.valid = false; } AlsaAudioBackend::~AlsaAudioBackend () @@ -111,7 +118,7 @@ AlsaAudioBackend::enumerate_input_devices () const _input_audio_device_status.clear(); std::map devices; get_alsa_audio_device_names(devices, HalfDuplexIn); - _input_audio_device_status.push_back (DeviceStatus (_("None"), true)); + _input_audio_device_status.push_back (DeviceStatus (get_standard_device_name(DeviceNone), true)); for (std::map::const_iterator i = devices.begin (); i != devices.end(); ++i) { if (_input_audio_device == "") _input_audio_device = i->first; _input_audio_device_status.push_back (DeviceStatus (i->first, true)); @@ -125,7 +132,7 @@ AlsaAudioBackend::enumerate_output_devices () const _output_audio_device_status.clear(); std::map devices; get_alsa_audio_device_names(devices, HalfDuplexOut); - _output_audio_device_status.push_back (DeviceStatus (_("None"), true)); + _output_audio_device_status.push_back (DeviceStatus (get_standard_device_name(DeviceNone), true)); for (std::map::const_iterator i = devices.begin (); i != devices.end(); ++i) { if (_output_audio_device == "") _output_audio_device = i->first; _output_audio_device_status.push_back (DeviceStatus (i->first, true)); @@ -211,47 +218,127 @@ AlsaAudioBackend::acquire_device(const char* device_name) } std::vector -AlsaAudioBackend::available_sample_rates (const std::string&) const +AlsaAudioBackend::available_sample_rates2 (const std::string& input_device, const std::string& output_device) const +{ + std::vector sr; + if (input_device == get_standard_device_name(DeviceNone) && output_device == get_standard_device_name(DeviceNone)) { + return sr; + } + else if (input_device == get_standard_device_name(DeviceNone)) { + sr = available_sample_rates (output_device); + } + else if (output_device == get_standard_device_name(DeviceNone)) { + sr = available_sample_rates (input_device); + } else { + std::vector sr_in = available_sample_rates (input_device); + std::vector sr_out = available_sample_rates (output_device); + std::set_intersection (sr_in.begin(), sr_in.end(), sr_out.begin(), sr_out.end(), std::back_inserter(sr)); + } + return sr; +} + +std::vector +AlsaAudioBackend::available_sample_rates (const std::string& device) const { + ALSADeviceInfo *nfo = NULL; std::vector sr; - sr.push_back (8000.0); - sr.push_back (22050.0); - sr.push_back (24000.0); - sr.push_back (44100.0); - sr.push_back (48000.0); - sr.push_back (88200.0); - sr.push_back (96000.0); - sr.push_back (176400.0); - sr.push_back (192000.0); + if (device == get_standard_device_name(DeviceNone)) { + return sr; + } + if (device == _input_audio_device && _input_audio_device_info.valid) { + nfo = &_input_audio_device_info; + } + else if (device == _output_audio_device && _output_audio_device_info.valid) { + nfo = &_output_audio_device_info; + } + + static const float avail_rates [] = { 8000, 22050.0, 24000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 }; + + for (size_t i = 0 ; i < sizeof(avail_rates) / sizeof(float); ++i) { + if (!nfo || (avail_rates[i] >= nfo->min_rate && avail_rates[i] <= nfo->max_rate)) { + sr.push_back (avail_rates[i]); + } + } + return sr; } std::vector -AlsaAudioBackend::available_buffer_sizes (const std::string&) const +AlsaAudioBackend::available_buffer_sizes2 (const std::string& input_device, const std::string& output_device) const +{ + std::vector bs; + if (input_device == get_standard_device_name(DeviceNone) && output_device == get_standard_device_name(DeviceNone)) { + return bs; + } + else if (input_device == get_standard_device_name(DeviceNone)) { + bs = available_buffer_sizes (output_device); + } + else if (output_device == get_standard_device_name(DeviceNone)) { + bs = available_buffer_sizes (input_device); + } else { + std::vector bs_in = available_buffer_sizes (input_device); + std::vector bs_out = available_buffer_sizes (output_device); + std::set_intersection (bs_in.begin(), bs_in.end(), bs_out.begin(), bs_out.end(), std::back_inserter(bs)); + } + return bs; +} + +std::vector +AlsaAudioBackend::available_buffer_sizes (const std::string& device) const { + ALSADeviceInfo *nfo = NULL; std::vector bs; - bs.push_back (32); - bs.push_back (64); - bs.push_back (128); - bs.push_back (256); - bs.push_back (512); - bs.push_back (1024); - bs.push_back (2048); - bs.push_back (4096); - bs.push_back (8192); + if (device == get_standard_device_name(DeviceNone)) { + return bs; + } + if (device == _input_audio_device && _input_audio_device_info.valid) { + nfo = &_input_audio_device_info; + } + else if (device == _output_audio_device && _output_audio_device_info.valid) { + nfo = &_output_audio_device_info; + } + + static const unsigned long avail_sizes [] = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; + + for (size_t i = 0 ; i < sizeof(avail_sizes) / sizeof(unsigned long); ++i) { + if (!nfo || (avail_sizes[i] >= nfo->min_size && avail_sizes[i] <= nfo->max_size)) { + bs.push_back (avail_sizes[i]); + } + } return bs; } uint32_t -AlsaAudioBackend::available_input_channel_count (const std::string&) const +AlsaAudioBackend::available_input_channel_count (const std::string& device) const { - return 128; // TODO query current device + if (device == get_standard_device_name(DeviceNone)) { + return 0; + } + if (device == _input_audio_device && _input_audio_device_info.valid) { + return _input_audio_device_info.max_channels; + } + return 128; } uint32_t -AlsaAudioBackend::available_output_channel_count (const std::string&) const +AlsaAudioBackend::available_output_channel_count (const std::string& device) const +{ + if (device == get_standard_device_name(DeviceNone)) { + return 0; + } + if (device == _output_audio_device && _output_audio_device_info.valid) { + return _output_audio_device_info.max_channels; + } + return 128; +} + +std::vector +AlsaAudioBackend::available_period_sizes (const std::string& driver) const { - return 128; // TODO query current device + std::vector ps; + ps.push_back (2); + ps.push_back (3); + return ps; } bool @@ -269,14 +356,62 @@ AlsaAudioBackend::can_change_buffer_size_when_running () const int AlsaAudioBackend::set_input_device_name (const std::string& d) { + if (_input_audio_device == d) { + return 0; + } _input_audio_device = d; + + if (d == get_standard_device_name(DeviceNone)) { + _input_audio_device_info.valid = false; + return 0; + } + std::string alsa_device; + std::map devices; + + get_alsa_audio_device_names(devices, HalfDuplexIn); + for (std::map::const_iterator i = devices.begin (); i != devices.end(); ++i) { + if (i->first == d) { + alsa_device = i->second; + break; + } + } + if (alsa_device == "") { + _input_audio_device_info.valid = false; + return 1; + } + /* device will be busy once used, hence cache the parameters */ + /* return */ get_alsa_device_parameters (alsa_device.c_str(), true, &_input_audio_device_info); return 0; } int AlsaAudioBackend::set_output_device_name (const std::string& d) { + if (_output_audio_device == d) { + return 0; + } + _output_audio_device = d; + + if (d == get_standard_device_name(DeviceNone)) { + _output_audio_device_info.valid = false; + return 0; + } + std::string alsa_device; + std::map devices; + + get_alsa_audio_device_names(devices, HalfDuplexOut); + for (std::map::const_iterator i = devices.begin (); i != devices.end(); ++i) { + if (i->first == d) { + alsa_device = i->second; + break; + } + } + if (alsa_device == "") { + _output_audio_device_info.valid = false; + return 1; + } + /* return */ get_alsa_device_parameters (alsa_device.c_str(), true, &_output_audio_device_info); return 0; } @@ -298,6 +433,19 @@ AlsaAudioBackend::set_sample_rate (float sr) return 0; } +int +AlsaAudioBackend::set_peridod_size (uint32_t n) +{ + if (n == 0 || n > 3) { + return -1; + } + if (_run) { + return -1; + } + _periods_per_cycle = n; + return 0; +} + int AlsaAudioBackend::set_buffer_size (uint32_t bs) { @@ -337,6 +485,9 @@ int AlsaAudioBackend::set_systemic_input_latency (uint32_t sl) { _systemic_audio_input_latency = sl; + if (_run) { + update_systemic_audio_latencies(); + } return 0; } @@ -344,6 +495,9 @@ int AlsaAudioBackend::set_systemic_output_latency (uint32_t sl) { _systemic_audio_output_latency = sl; + if (_run) { + update_systemic_audio_latencies(); + } return 0; } @@ -353,6 +507,9 @@ AlsaAudioBackend::set_systemic_midi_input_latency (std::string const device, uin struct AlsaMidiDeviceInfo * nfo = midi_device_info(device); if (!nfo) return -1; nfo->systemic_input_latency = sl; + if (_run && nfo->enabled) { + update_systemic_midi_latencies (); + } return 0; } @@ -362,17 +519,65 @@ AlsaAudioBackend::set_systemic_midi_output_latency (std::string const device, ui struct AlsaMidiDeviceInfo * nfo = midi_device_info(device); if (!nfo) return -1; nfo->systemic_output_latency = sl; + if (_run && nfo->enabled) { + update_systemic_midi_latencies (); + } return 0; } +void +AlsaAudioBackend::update_systemic_audio_latencies () +{ + const uint32_t lcpp = (_periods_per_cycle - 2) * _samples_per_period; + LatencyRange lr; + + lr.min = lr.max = lcpp + (_measure_latency ? 0 : _systemic_audio_input_latency); + for (std::vector::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) { + set_latency_range (*it, true, lr); + } + + lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_output_latency); + for (std::vector::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) { + set_latency_range (*it, false, lr); + } + update_latencies (); +} + +void +AlsaAudioBackend::update_systemic_midi_latencies () +{ + uint32_t i = 0; + for (std::vector::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) { + assert (_rmidi_out.size() > i); + AlsaMidiOut *rm = _rmidi_out.at(i); + struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name()); + assert (nfo); + LatencyRange lr; + lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency); + set_latency_range (*it, false, lr); + } + + i = 0; + for (std::vector::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) { + assert (_rmidi_in.size() > i); + AlsaMidiIO *rm = _rmidi_in.at(i); + struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name()); + assert (nfo); + LatencyRange lr; + lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_input_latency); + set_latency_range (*it, true, lr); + } + update_latencies (); +} + /* Retrieving parameters */ std::string AlsaAudioBackend::device_name () const { - if (_input_audio_device != _("None")) { + if (_input_audio_device != get_standard_device_name(DeviceNone)) { return _input_audio_device; } - if (_output_audio_device != _("None")) { + if (_output_audio_device != get_standard_device_name(DeviceNone)) { return _output_audio_device; } return ""; @@ -402,6 +607,12 @@ AlsaAudioBackend::buffer_size () const return _samples_per_period; } +uint32_t +AlsaAudioBackend::period_size () const +{ + return _periods_per_cycle; +} + bool AlsaAudioBackend::interleaved () const { @@ -457,7 +668,7 @@ AlsaAudioBackend::midi_device_info(std::string const name) const { } } - assert(_midi_driver_option != _("None")); + assert(_midi_driver_option != get_standard_device_name(DeviceNone)); std::map devices; if (_midi_driver_option == _("ALSA raw devices")) { @@ -481,7 +692,7 @@ AlsaAudioBackend::enumerate_midi_options () const if (_midi_options.empty()) { _midi_options.push_back (_("ALSA raw devices")); _midi_options.push_back (_("ALSA sequencer")); - _midi_options.push_back (_("None")); + _midi_options.push_back (get_standard_device_name(DeviceNone)); } return _midi_options; } @@ -508,7 +719,10 @@ AlsaAudioBackend::enumerate_midi_devices () const int AlsaAudioBackend::set_midi_option (const std::string& opt) { - if (opt != _("None") && opt != _("ALSA raw devices") && opt != _("ALSA sequencer")) { + if (opt != get_standard_device_name(DeviceNone) && opt != _("ALSA raw devices") && opt != _("ALSA sequencer")) { + return -1; + } + if (_run && _midi_driver_option != opt) { return -1; } _midi_driver_option = opt; @@ -526,7 +740,41 @@ AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable { struct AlsaMidiDeviceInfo * nfo = midi_device_info(device); if (!nfo) return -1; + const bool prev_enabled = nfo->enabled; nfo->enabled = enable; + + if (_run && prev_enabled != enable) { + if (enable) { + // add ports for the given device + register_system_midi_ports(device); + } else { + // remove all ports provided by the given device + uint32_t i = 0; + for (std::vector::iterator it = _system_midi_out.begin (); it != _system_midi_out.end ();) { + assert (_rmidi_out.size() > i); + AlsaMidiOut *rm = _rmidi_out.at(i); + if (rm->name () != device) { ++it; ++i; continue; } + it = _system_midi_out.erase (it); + unregister_port (*it); + rm->stop(); + _rmidi_out.erase (_rmidi_out.begin() + i); + delete rm; + } + + i = 0; + for (std::vector::iterator it = _system_midi_in.begin (); it != _system_midi_in.end ();) { + assert (_rmidi_in.size() > i); + AlsaMidiIn *rm = _rmidi_in.at(i); + if (rm->name () != device) { ++it; ++i; continue; } + it = _system_midi_in.erase (it); + unregister_port (*it); + rm->stop(); + _rmidi_in.erase (_rmidi_in.begin() + i); + delete rm; + } + } + update_systemic_midi_latencies (); + } return 0; } @@ -558,7 +806,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement) if (_active || _run) { PBD::error << _("AlsaAudioBackend: already active.") << endmsg; - return -1; + return BackendReinitializationError; } if (_ports.size()) { @@ -587,17 +835,17 @@ AlsaAudioBackend::_start (bool for_latency_measurement) std::string alsa_device; std::map devices; - if (_input_audio_device == _("None") && _output_audio_device == _("None")) { + if (_input_audio_device == get_standard_device_name(DeviceNone) && _output_audio_device == get_standard_device_name(DeviceNone)) { PBD::error << _("AlsaAudioBackend: At least one of input or output device needs to be set."); - return -1; + return AudioDeviceInvalidError; } if (_input_audio_device != _output_audio_device) { - if (_input_audio_device != _("None") && _output_audio_device != _("None")) { + if (_input_audio_device != get_standard_device_name(DeviceNone) && _output_audio_device != get_standard_device_name(DeviceNone)) { PBD::error << _("AlsaAudioBackend: Cannot use two different devices."); - return -1; + return AudioDeviceInvalidError; } - if (_input_audio_device != _("None")) { + if (_input_audio_device != get_standard_device_name(DeviceNone)) { get_alsa_audio_device_names(devices, HalfDuplexIn); audio_device = _input_audio_device; duplex = 1; @@ -620,28 +868,59 @@ AlsaAudioBackend::_start (bool for_latency_measurement) } if (alsa_device == "") { PBD::error << _("AlsaAudioBackend: Cannot find configured device. Is it still connected?"); - return -1; + return AudioDeviceNotAvailableError; } acquire_device(alsa_device.c_str()); _pcmi = new Alsa_pcmi ( (duplex & 2) ? alsa_device.c_str() : NULL, (duplex & 1) ? alsa_device.c_str() : NULL, - 0, _samplerate, _samples_per_period, _periods_per_cycle, 0); - switch (_pcmi->state ()) { - case 0: /* OK */ break; - case -1: PBD::error << _("AlsaAudioBackend: failed to open device.") << endmsg; break; - case -2: PBD::error << _("AlsaAudioBackend: failed to allocate parameters.") << endmsg; break; - case -3: PBD::error << _("AlsaAudioBackend: cannot set requested sample rate.") << endmsg; break; - case -4: PBD::error << _("AlsaAudioBackend: cannot set requested period size.") << endmsg; break; - case -5: PBD::error << _("AlsaAudioBackend: cannot set requested number of periods.") << endmsg; break; - case -6: PBD::error << _("AlsaAudioBackend: unsupported sample format.") << endmsg; break; - default: PBD::error << _("AlsaAudioBackend: initialization failed.") << endmsg; break; + /* ctrl name */ 0, + _samplerate, _samples_per_period, + _periods_per_cycle, /* _periods_per_cycle */ 2, + /* debug */ 0); + + AudioBackend::ErrorCode error_code = NoError; + switch (_pcmi->state()) { + case 0: /* OK */ + break; + case -1: + PBD::error << _("AlsaAudioBackend: failed to open device.") << endmsg; + error_code = AudioDeviceOpenError; + break; + case -2: + PBD::error << _("AlsaAudioBackend: failed to allocate parameters.") << endmsg; + error_code = AudioDeviceOpenError; + break; + case -3: + PBD::error << _("AlsaAudioBackend: cannot set requested sample rate.") + << endmsg; + error_code = SampleRateNotSupportedError; + break; + case -4: + PBD::error << _("AlsaAudioBackend: cannot set requested period size.") + << endmsg; + error_code = PeriodSizeNotSupportedError; + break; + case -5: + PBD::error << _("AlsaAudioBackend: cannot set requested number of periods.") + << endmsg; + error_code = PeriodCountNotSupportedError; + break; + case -6: + PBD::error << _("AlsaAudioBackend: unsupported sample format.") << endmsg; + error_code = SampleFormatNotSupportedError; + break; + default: + PBD::error << _("AlsaAudioBackend: initialization failed.") << endmsg; + error_code = AudioDeviceOpenError; + break; } + if (_pcmi->state ()) { delete _pcmi; _pcmi = 0; release_device(); - return -1; + return error_code; } #ifndef NDEBUG @@ -679,13 +958,14 @@ AlsaAudioBackend::_start (bool for_latency_measurement) _measure_latency = for_latency_measurement; + _midi_ins = _midi_outs = 0; register_system_midi_ports(); if (register_system_audio_ports()) { PBD::error << _("AlsaAudioBackend: failed to register system ports.") << endmsg; delete _pcmi; _pcmi = 0; release_device(); - return -1; + return PortRegistrationError; } engine.sample_rate_change (_samplerate); @@ -695,7 +975,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement) PBD::error << _("AlsaAudioBackend: Could not re-establish ports.") << endmsg; delete _pcmi; _pcmi = 0; release_device(); - return -1; + return PortReconnectError; } engine.reconnect_ports (); @@ -711,7 +991,7 @@ AlsaAudioBackend::_start (bool for_latency_measurement) delete _pcmi; _pcmi = 0; release_device(); _run = false; - return -1; + return ProcessThreadStartError; } else { PBD::warning << _("AlsaAudioBackend: cannot acquire realtime permissions.") << endmsg; } @@ -725,10 +1005,10 @@ AlsaAudioBackend::_start (bool for_latency_measurement) delete _pcmi; _pcmi = 0; release_device(); _run = false; - return -1; + return ProcessThreadStartError; } - return 0; + return NoError; } int @@ -760,6 +1040,7 @@ AlsaAudioBackend::stop () unregister_ports(); delete _pcmi; _pcmi = 0; + _midi_ins = _midi_outs = 0; release_device(); return (_active == false) ? 0 : -1; @@ -775,7 +1056,7 @@ AlsaAudioBackend::freewheel (bool onoff) float AlsaAudioBackend::dsp_load () const { - return std::min(100.f, 100.f * _dsp_load); + return 100.f * _dsp_load; } size_t @@ -1056,6 +1337,8 @@ AlsaAudioBackend::register_system_audio_ports() const int a_ins = _n_inputs; const int a_out = _n_outputs; + const uint32_t lcpp = (_periods_per_cycle - 2) * _samples_per_period; + /* audio ports */ lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_input_latency); for (int i = 1; i <= a_ins; ++i) { @@ -1067,7 +1350,7 @@ AlsaAudioBackend::register_system_audio_ports() _system_inputs.push_back(static_cast(p)); } - lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_output_latency); + lr.min = lr.max = lcpp + (_measure_latency ? 0 : _systemic_audio_output_latency); for (int i = 1; i <= a_out; ++i) { char tmp[64]; snprintf(tmp, sizeof(tmp), "system:playback_%d", i); @@ -1080,13 +1363,13 @@ AlsaAudioBackend::register_system_audio_ports() } int -AlsaAudioBackend::register_system_midi_ports() +AlsaAudioBackend::register_system_midi_ports(const std::string device) { std::map devices; - int midi_ins = 0; - int midi_outs = 0; - if (_midi_driver_option == _("None")) { + // TODO use consistent numbering when re-adding devices: _midi_ins, _midi_outs + + if (_midi_driver_option == get_standard_device_name(DeviceNone)) { return 0; } else if (_midi_driver_option == _("ALSA raw devices")) { get_alsa_rawmidi_device_names(devices); @@ -1095,15 +1378,18 @@ AlsaAudioBackend::register_system_midi_ports() } for (std::map::const_iterator i = devices.begin (); i != devices.end(); ++i) { + if (!device.empty() && device != i->first) { + continue; + } struct AlsaMidiDeviceInfo * nfo = midi_device_info(i->first); if (!nfo) continue; if (!nfo->enabled) continue; AlsaMidiOut *mout; if (_midi_driver_option == _("ALSA raw devices")) { - mout = new AlsaRawMidiOut (i->second.c_str()); + mout = new AlsaRawMidiOut (i->first, i->second.c_str()); } else { - mout = new AlsaSeqMidiOut (i->second.c_str()); + mout = new AlsaSeqMidiOut (i->first, i->second.c_str()); } if (mout->state ()) { @@ -1121,7 +1407,7 @@ AlsaAudioBackend::register_system_midi_ports() delete mout; } else { char tmp[64]; - snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++midi_ins); + snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++_midi_ins); PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast(IsInput | IsPhysical | IsTerminal)); if (!p) { mout->stop(); @@ -1129,8 +1415,8 @@ AlsaAudioBackend::register_system_midi_ports() } LatencyRange lr; lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency); - set_latency_range (p, false, lr); - static_cast(p)->set_n_periods(2); + set_latency_range (p, true, lr); + static_cast(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment _system_midi_out.push_back(static_cast(p)); _rmidi_out.push_back (mout); } @@ -1138,9 +1424,9 @@ AlsaAudioBackend::register_system_midi_ports() AlsaMidiIn *midin; if (_midi_driver_option == _("ALSA raw devices")) { - midin = new AlsaRawMidiIn (i->second.c_str()); + midin = new AlsaRawMidiIn (i->first, i->second.c_str()); } else { - midin = new AlsaSeqMidiIn (i->second.c_str()); + midin = new AlsaSeqMidiIn (i->first, i->second.c_str()); } if (midin->state ()) { @@ -1158,7 +1444,7 @@ AlsaAudioBackend::register_system_midi_ports() delete midin; } else { char tmp[64]; - snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++midi_outs); + snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++_midi_outs); PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast(IsOutput | IsPhysical | IsTerminal)); if (!p) { midin->stop(); @@ -1529,11 +1815,10 @@ AlsaAudioBackend::main_process_thread () _active = true; _processed_samples = 0; - uint64_t clock1, clock2; + uint64_t clock1; _pcmi->pcm_start (); int no_proc_errors = 0; const int bailout = 2 * _samplerate / _samples_per_period; - const int64_t nominal_time = 1e6 * _samples_per_period / _samplerate; manager.registration_callback(); manager.graph_order_callback(); @@ -1636,17 +1921,10 @@ AlsaAudioBackend::main_process_thread () nr -= _samples_per_period; _processed_samples += _samples_per_period; - /* calculate DSP load */ - clock2 = g_get_monotonic_time(); - const int64_t elapsed_time = clock2 - clock1; - // low pass filter - const float load = elapsed_time / (float) nominal_time; - if (load > _dsp_load) { - _dsp_load = load; - } else { - const float a = .2 * _samples_per_period / _samplerate; - _dsp_load = _dsp_load + a * (load - _dsp_load) + 1e-12; - } + _dsp_load_calc.set_max_time(_samplerate, _samples_per_period); + _dsp_load_calc.set_start_timestamp_us (clock1); + _dsp_load_calc.set_stop_timestamp_us (g_get_monotonic_time()); + _dsp_load = _dsp_load_calc.get_dsp_load (); } if (xrun && (_pcmi->capt_xrun() > 0 || _pcmi->play_xrun() > 0)) {