From 7dfdc5e3e2434766a787214cba273a35be42bc62 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 28 Dec 2022 16:57:05 +0000 Subject: [PATCH] Move audio device selection to dedicated class --- audiodevices.cpp | 322 +++++++++++++++++++++++++++ audiodevices.h | 73 +++++++ wfmain.cpp | 327 ++++------------------------ wfmain.h | 2 + wfview.pro | 6 +- wfview.vcxproj | 479 +++++++++++++++++++++++++++++++++-------- wfview.vcxproj.filters | 80 ++++++- 7 files changed, 909 insertions(+), 380 deletions(-) create mode 100644 audiodevices.cpp create mode 100644 audiodevices.h diff --git a/audiodevices.cpp b/audiodevices.cpp new file mode 100644 index 0000000..6a05d3b --- /dev/null +++ b/audiodevices.cpp @@ -0,0 +1,322 @@ +/* + wfview class to enumerate audio devices and assist with matching saved devices + + Written by Phil Taylor M0VSE Nov 2022. + +*/ + +#include "audiodevices.h" +#include "logcategories.h" + +audioDevices::audioDevices(audioType type, QFontMetrics fm, QObject* parent) : + system(type), + fm(fm), + QObject(parent) +{ + +} + + +void audioDevices::enumerate() +{ + numInputDevices = 0; + numOutputDevices = 0; + numCharsIn = 0; + numCharsOut = 0; + inputs.clear(); + outputs.clear(); + switch (system) + { + case qtAudio: + { + Pa_Terminate(); + + foreach(const QAudioDeviceInfo & deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) + { + bool isDefault = false; + if (numInputDevices == 0) { + defaultInputDeviceName = QString(deviceInfo.deviceName()); + } +#ifdef Q_OS_WIN + if (deviceInfo.realm() == "wasapi") { +#endif + /* Append Input Device Here */ + if (deviceInfo.deviceName() == defaultInputDeviceName) { + isDefault = true; + } + inputs.append(audioDevice(deviceInfo.deviceName(), deviceInfo, deviceInfo.realm(),isDefault )); + + if (fm.boundingRect(deviceInfo.deviceName()).width() > numCharsIn) + numCharsIn = fm.boundingRect(deviceInfo.deviceName()).width(); + +#ifdef Q_OS_WIN + } +#endif + numInputDevices++; + } + + foreach(const QAudioDeviceInfo & deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) + { + bool isDefault = false; + if (numOutputDevices == 0) + { + defaultOutputDeviceName = QString(deviceInfo.deviceName()); + } +#ifdef Q_OS_WIN + if (deviceInfo.realm() == "wasapi") { +#endif + /* Append Output Device Here */ + if (deviceInfo.deviceName() == defaultOutputDeviceName) { + isDefault = true; + } + outputs.append(audioDevice(deviceInfo.deviceName(), deviceInfo, deviceInfo.realm(),isDefault)); + if (fm.boundingRect(deviceInfo.deviceName()).width() > numCharsOut) + numCharsOut = fm.boundingRect(deviceInfo.deviceName()).width(); + +#ifdef Q_OS_WIN + } +#endif + numOutputDevices++; + } + break; + } + case portAudio: + { + PaError err; + + err = Pa_Initialize(); + + if (err != paNoError) + { + qInfo(logAudio()) << "ERROR: Cannot initialize Portaudio"; + return; + } + + qInfo(logAudio()) << "PortAudio version: " << Pa_GetVersionInfo()->versionText; + + int numDevices = Pa_GetDeviceCount(); + qInfo(logAudio()) << "Pa_CountDevices returned" << numDevices; + + const PaDeviceInfo* info; + for (int i = 0; i < numDevices; i++) + { + info = Pa_GetDeviceInfo(i); + if (info->maxInputChannels > 0) { + bool isDefault = false; + numInputDevices++; + qDebug(logAudio()) << (i == Pa_GetDefaultInputDevice() ? "*" : " ") << "(" << i << ") Input Device : " << QString(info->name); + if (i == Pa_GetDefaultInputDevice()) { + defaultInputDeviceName = info->name; + isDefault = true; + } + inputs.append(audioDevice(QString(info->name), i,isDefault)); + if (fm.boundingRect(QString(info->name)).width() > numCharsIn) + numCharsIn = fm.boundingRect(QString(info->name)).width(); + + } + if (info->maxOutputChannels > 0) { + bool isDefault = false; + numOutputDevices++; + qDebug(logAudio()) << (i == Pa_GetDefaultOutputDevice() ? "*" : " ") << "(" << i << ") Output Device : " << QString(info->name); + if (i == Pa_GetDefaultOutputDevice()) { + defaultOutputDeviceName = info->name; + isDefault = true; + } + outputs.append(audioDevice(QString(info->name), i,isDefault)); + if (fm.boundingRect(QString(info->name)).width() > numCharsOut) + numCharsOut = fm.boundingRect(QString(info->name)).width(); + } + } + break; + } + case rtAudio: + { + Pa_Terminate(); + +#if defined(Q_OS_LINUX) + RtAudio* audio = new RtAudio(RtAudio::Api::LINUX_ALSA); +#elif defined(Q_OS_WIN) + RtAudio* audio = new RtAudio(RtAudio::Api::WINDOWS_WASAPI); +#elif defined(Q_OS_MACX) + RtAudio* audio = new RtAudio(RtAudio::Api::MACOSX_CORE); +#endif + + + // Enumerate audio devices, need to do before settings are loaded. + std::map apiMap; + apiMap[RtAudio::MACOSX_CORE] = "OS-X Core Audio"; + apiMap[RtAudio::WINDOWS_ASIO] = "Windows ASIO"; + apiMap[RtAudio::WINDOWS_DS] = "Windows DirectSound"; + apiMap[RtAudio::WINDOWS_WASAPI] = "Windows WASAPI"; + apiMap[RtAudio::UNIX_JACK] = "Jack Client"; + apiMap[RtAudio::LINUX_ALSA] = "Linux ALSA"; + apiMap[RtAudio::LINUX_PULSE] = "Linux PulseAudio"; + apiMap[RtAudio::LINUX_OSS] = "Linux OSS"; + apiMap[RtAudio::RTAUDIO_DUMMY] = "RtAudio Dummy"; + + std::vector< RtAudio::Api > apis; + RtAudio::getCompiledApi(apis); + + qInfo(logAudio()) << "RtAudio Version " << QString::fromStdString(RtAudio::getVersion()); + + qInfo(logAudio()) << "Compiled APIs:"; + for (unsigned int i = 0; i < apis.size(); i++) { + qInfo(logAudio()) << " " << QString::fromStdString(apiMap[apis[i]]); + } + + RtAudio::DeviceInfo info; + + qInfo(logAudio()) << "Current API: " << QString::fromStdString(apiMap[audio->getCurrentApi()]); + + unsigned int devices = audio->getDeviceCount(); + qInfo(logAudio()) << "Found " << devices << " audio device(s) *=default"; + + for (unsigned int i = 1; i < devices; i++) { + info = audio->getDeviceInfo(i); + if (info.inputChannels > 0) { + bool isDefault = false; + qInfo(logAudio()) << (info.isDefaultInput ? "*" : " ") << "(" << i << ") Input Device : " << QString::fromStdString(info.name); + numInputDevices++; + + if (info.isDefaultInput) { + defaultInputDeviceName = QString::fromStdString(info.name); + isDefault = true; + } + + inputs.append(audioDevice(QString::fromStdString(info.name), i, isDefault)); + + if (fm.boundingRect(QString::fromStdString(info.name)).width() > numCharsIn) + numCharsIn = fm.boundingRect(QString::fromStdString(info.name)).width(); + + } + if (info.outputChannels > 0) { + bool isDefault = false; + qInfo(logAudio()) << (info.isDefaultOutput ? "*" : " ") << "(" << i << ") Output Device : " << QString::fromStdString(info.name); + numOutputDevices++; + + if (info.isDefaultOutput) { + defaultOutputDeviceName = QString::fromStdString(info.name); + isDefault = true; + } + + outputs.append(audioDevice(QString::fromStdString(info.name), i, isDefault)); + + if (fm.boundingRect(QString::fromStdString(info.name)).width() > numCharsOut) + numCharsOut = fm.boundingRect(QString::fromStdString(info.name)).width(); + } + } + + delete audio; + break; + } + + } + emit updated(); + +} + +audioDevices::~audioDevices() +{ + +} + +QStringList audioDevices::getInputs() +{ + QStringList list; + foreach(const audioDevice input, inputs) { + list.append(input.name); + } + + return list; +} + +QStringList audioDevices::getOutputs() +{ + QStringList list; + foreach(const audioDevice output, outputs) { + list.append(output.name); + } + + return list; +} + +int audioDevices::findInput(QString type, QString name) +{ + int ret = -1; + int def = -1; + QString msg; + QTextStream s(&msg); + for (int f = 0; f < inputs.size(); f++) + { + //qInfo(logAudio()) << "Found device" << inputs[f].name; + if (inputs[f].name.startsWith(name)) { + s << type << " Audio input device " << name << " found! "; + ret = f; + } + if (inputs[f].isDefault == true) + { + def = f; + } + } + + if (ret == -1) + { + s << type << " Audio input device " << name << " Not found: "; + + if (inputs.size() == 1) { + s << "Selecting first device " << inputs[0].name; + ret = 0; + } + else if (def > -1) + { + s << " Selecting default device " << inputs[def].name; + ret = def; + } + else { + s << " and no default device found, aborting!"; + } + } + + qInfo(logAudio()) << msg; + return ret; +} + +int audioDevices::findOutput(QString type, QString name) +{ + int ret = -1; + int def = -1; + QString msg; + QTextStream s(&msg); + for (int f = 0; f < outputs.size(); f++) + { + //qInfo(logAudio()) << "Found device" << outputs[f].name; + if (outputs[f].name.startsWith(name)) { + ret = f; + s << type << " Audio output device " << name << " found! "; + } + if (outputs[f].isDefault == true) + { + def = f; + } + } + + if (ret == -1) + { + s << type << " Audio output device " << name << " Not found: "; + + if (outputs.size() == 1) { + s << " Selecting first device " << outputs[0].name; + ret = 0; + } + else if (def > -1) + { + s << " Selecting default device " << outputs[def].name; + ret = def; + } + else { + s << " and no default device found, aborting!"; + } + } + qInfo(logAudio()) << msg; + return ret; +} \ No newline at end of file diff --git a/audiodevices.h b/audiodevices.h new file mode 100644 index 0000000..e885dc9 --- /dev/null +++ b/audiodevices.h @@ -0,0 +1,73 @@ +#ifndef AUDIODEVICES_H +#define AUDIODEVICES_H +#include +#include +#include + +#include +#ifndef Q_OS_LINUX +#include "RtAudio.h" +#else +#include "rtaudio/RtAudio.h" +#endif + +#include "wfviewtypes.h" + +struct audioDevice { + audioDevice(QString name, int deviceInt, bool isDefault) : name(name), deviceInt(deviceInt), isDefault(isDefault) {}; + audioDevice(QString name, const QAudioDeviceInfo deviceInfo, QString realm, bool isDefault) : name(name), deviceInfo(deviceInfo), realm(realm), isDefault(isDefault) {}; + + QString name; + int deviceInt; + const QAudioDeviceInfo deviceInfo; + QString realm; + bool isDefault; +}; + +class audioDevices : public QObject +{ + Q_OBJECT + +public: + explicit audioDevices(audioType type, QFontMetrics fm, QObject* parent = nullptr); + ~audioDevices(); + void setAudioType(audioType type) { system = type; }; + audioType getAudioType() { return system; }; + int getNumCharsIn() { return numCharsIn; }; + int getNumCharsOut() { return numCharsOut; }; + + QString getInputName(int num) { return inputs[num].name; }; + QString getOutputName(int num) { return outputs[num].name; }; + + int getInputDeviceInt(int num) { return inputs[num].deviceInt; }; + int getOutputDeviceInt(int num) { return outputs[num].deviceInt; }; + const QAudioDeviceInfo getInputDeviceInfo(int num) { return inputs[num].deviceInfo; }; + const QAudioDeviceInfo getOutputDeviceInfo(int num) { return outputs[num].deviceInfo; }; + + void enumerate(); + + QStringList getInputs(); + QStringList getOutputs(); + + int findInput(QString type, QString name); + int findOutput(QString type, QString name); + +public slots: + +signals: + void updated(); +protected: +private: + QString defaultInputDeviceName; + QString defaultOutputDeviceName; + int numInputDevices; + int numOutputDevices; + audioType system; + QList inputs; + QList outputs; + QFontMetrics fm; + int numCharsIn = 0; + int numCharsOut = 0; +}; + +#endif \ No newline at end of file diff --git a/wfmain.cpp b/wfmain.cpp index d2270f3..44cb191 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2083,17 +2083,15 @@ void wfmain::on_serverRXAudioInputCombo_currentIndexChanged(int value) if (!serverConfig.rigs.isEmpty()) { if (prefs.audioSystem == qtAudio) { - QVariant v = ui->serverRXAudioInputCombo->itemData(value); - serverConfig.rigs.first()->rxAudioSetup.port = v.value(); + serverConfig.rigs.first()->rxAudioSetup.port = audioDev->getInputDeviceInfo(value); } else { - serverConfig.rigs.first()->rxAudioSetup.portInt = ui->serverRXAudioInputCombo->itemData(value).toInt(); + serverConfig.rigs.first()->rxAudioSetup.portInt = audioDev->getInputDeviceInt(value); } - serverConfig.rigs.first()->rxAudioSetup.name = ui->serverRXAudioInputCombo->itemText(value); + serverConfig.rigs.first()->rxAudioSetup.name = audioDev->getInputName(value); } - } void wfmain::on_serverTXAudioOutputCombo_currentIndexChanged(int value) @@ -2102,14 +2100,13 @@ void wfmain::on_serverTXAudioOutputCombo_currentIndexChanged(int value) if (!serverConfig.rigs.isEmpty()) { if (prefs.audioSystem == qtAudio) { - QVariant v = ui->serverTXAudioOutputCombo->itemData(value); - serverConfig.rigs.first()->txAudioSetup.port = v.value(); + serverConfig.rigs.first()->txAudioSetup.port = audioDev->getOutputDeviceInfo(value); } else { - serverConfig.rigs.first()->txAudioSetup.portInt = ui->serverTXAudioOutputCombo->itemData(value).toInt(); + serverConfig.rigs.first()->txAudioSetup.portInt = audioDev->getOutputDeviceInt(value); } - serverConfig.rigs.first()->txAudioSetup.name = ui->serverTXAudioOutputCombo->itemText(value); + serverConfig.rigs.first()->txAudioSetup.name = audioDev->getOutputName(value); } @@ -5166,14 +5163,13 @@ void wfmain::on_audioOutputCombo_currentIndexChanged(int value) { if (prefs.audioSystem == qtAudio) { - QVariant v = ui->audioOutputCombo->itemData(value); - rxSetup.port = v.value(); + rxSetup.port = audioDev->getOutputDeviceInfo(value); } else { - rxSetup.portInt = ui->audioOutputCombo->itemData(value).toInt(); + rxSetup.portInt = audioDev->getOutputDeviceInt(value); } - rxSetup.name = ui->audioOutputCombo->itemText(value); + rxSetup.name = audioDev->getOutputName(value); qDebug(logGui()) << "Changed audio output to:" << rxSetup.name; } @@ -5181,14 +5177,13 @@ void wfmain::on_audioInputCombo_currentIndexChanged(int value) { if (prefs.audioSystem == qtAudio) { - QVariant v = ui->audioInputCombo->itemData(value); - txSetup.port = v.value(); + txSetup.port = audioDev->getInputDeviceInfo(value); } else { - txSetup.portInt = ui->audioInputCombo->itemData(value).toInt(); + txSetup.portInt = audioDev->getInputDeviceInt(value); } - txSetup.name = ui->audioInputCombo->itemText(value); + txSetup.name = audioDev->getInputName(value); qDebug(logGui()) << "Changed audio input to:" << txSetup.name; } @@ -6375,286 +6370,56 @@ void wfmain::on_radioStatusBtn_clicked() void wfmain::setAudioDevicesUI() { - // Enumerate audio devices, need to do before settings are loaded, - // First clear all existing entries - ui->audioInputCombo->blockSignals(true); - ui->audioOutputCombo->blockSignals(true); - ui->serverTXAudioOutputCombo->blockSignals(true); - ui->serverRXAudioInputCombo->blockSignals(true); - - ui->audioInputCombo->clear(); - ui->audioOutputCombo->clear(); - ui->serverTXAudioOutputCombo->clear(); - ui->serverRXAudioInputCombo->clear(); - - qDebug(logSystem()) << "Finding audio devices, output=" << rxSetup.name << "input=" << txSetup.name; - - int defaultAudioInputIndex = 0; - int defaultAudioOutputIndex = 0; - int numCharsIn = 0; - int numCharsOut = 0; - QFontMetrics fm(ui->audioInputCombo->font()); - - ui->audioInputCombo->setCurrentIndex(-1); - ui->audioOutputCombo->setCurrentIndex(-1); - ui->serverRXAudioInputCombo->setCurrentIndex(-1); - ui->serverTXAudioOutputCombo->setCurrentIndex(-1); - QString defaultAudioInputName; - QString defaultAudioOutputName; - - switch (prefs.audioSystem) - { - case qtAudio: - { - Pa_Terminate(); - - int inCount = 0; - foreach(const QAudioDeviceInfo & deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) - { - if (inCount == 0) - defaultAudioInputName = QString(deviceInfo.deviceName().toLocal8Bit()); -#ifdef Q_OS_WIN - if (deviceInfo.realm() == "wasapi") { -#endif - ui->audioInputCombo->addItem(deviceInfo.deviceName().toLocal8Bit(), QVariant::fromValue(deviceInfo)); - ui->serverRXAudioInputCombo->addItem(deviceInfo.deviceName().toLocal8Bit(), QVariant::fromValue(deviceInfo)); - if (fm.boundingRect(deviceInfo.deviceName()).width() > numCharsIn) - numCharsIn = fm.boundingRect(deviceInfo.deviceName()).width(); -#ifdef Q_OS_WIN - } -#endif - inCount++; - } - - int outCount = 0; - foreach(const QAudioDeviceInfo & deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) - { - if (outCount == 0) - defaultAudioOutputName = QString(deviceInfo.deviceName().toLocal8Bit()); -#ifdef Q_OS_WIN - if (deviceInfo.realm() == "wasapi") { -#endif - ui->audioOutputCombo->addItem(deviceInfo.deviceName().toLocal8Bit(), QVariant::fromValue(deviceInfo)); - ui->serverTXAudioOutputCombo->addItem(deviceInfo.deviceName().toLocal8Bit(), QVariant::fromValue(deviceInfo)); - if (fm.boundingRect(deviceInfo.deviceName()).width() > numCharsOut) - numCharsOut = fm.boundingRect(deviceInfo.deviceName()).width(); - -#ifdef Q_OS_WIN - } -#endif - outCount++; - } - break; - } - case portAudio: - { - PaError err; - - err = Pa_Initialize(); - - if (err != paNoError) - { - qInfo(logAudio()) << "ERROR: Cannot initialize Portaudio"; - return; - } - - qInfo(logAudio()) << "PortAudio version: " << Pa_GetVersionInfo()->versionText; - - int numDevices = Pa_GetDeviceCount(); - qInfo(logAudio()) << "Pa_CountDevices returned" << numDevices; - - const PaDeviceInfo* info; - for (int i = 0; i < numDevices; i++) - { - info = Pa_GetDeviceInfo(i); - if (info->maxInputChannels > 0) { - qDebug(logAudio()) << (i == Pa_GetDefaultInputDevice() ? "*" : " ") << "(" << i << ") Input Device : " << QString(info->name).toLocal8Bit(); - - ui->audioInputCombo->addItem(QString(info->name).toLocal8Bit(), i); - ui->serverRXAudioInputCombo->addItem(QString(info->name).toLocal8Bit(), i); - - if (fm.boundingRect(QString(info->name)).width() > numCharsIn) - numCharsIn = fm.boundingRect(QString(info->name)).width(); - - if (i == Pa_GetDefaultInputDevice()) { - defaultAudioInputName = info->name; - } - } - if (info->maxOutputChannels > 0) { - qDebug(logAudio()) << (i == Pa_GetDefaultOutputDevice() ? "*" : " ") << "(" << i << ") Output Device : " << QString(info->name).toLocal8Bit(); - ui->audioOutputCombo->addItem(QString(info->name).toLocal8Bit(), i); - ui->serverTXAudioOutputCombo->addItem(QString(info->name).toLocal8Bit(), i); - - if (fm.boundingRect(QString(info->name)).width() > numCharsOut) - numCharsOut = fm.boundingRect(QString(info->name)).width(); - - if (i == Pa_GetDefaultOutputDevice()) { - defaultAudioOutputName = info->name; - } - } - } - break; - } - case rtAudio: - { - Pa_Terminate(); - -#if defined(Q_OS_LINUX) - RtAudio* audio = new RtAudio(RtAudio::Api::LINUX_ALSA); -#elif defined(Q_OS_WIN) - RtAudio* audio = new RtAudio(RtAudio::Api::WINDOWS_WASAPI); -#elif defined(Q_OS_MACX) - RtAudio* audio = new RtAudio(RtAudio::Api::MACOSX_CORE); -#endif - - - // Enumerate audio devices, need to do before settings are loaded. - std::map apiMap; - apiMap[RtAudio::MACOSX_CORE] = "OS-X Core Audio"; - apiMap[RtAudio::WINDOWS_ASIO] = "Windows ASIO"; - apiMap[RtAudio::WINDOWS_DS] = "Windows DirectSound"; - apiMap[RtAudio::WINDOWS_WASAPI] = "Windows WASAPI"; - apiMap[RtAudio::UNIX_JACK] = "Jack Client"; - apiMap[RtAudio::LINUX_ALSA] = "Linux ALSA"; - apiMap[RtAudio::LINUX_PULSE] = "Linux PulseAudio"; - apiMap[RtAudio::LINUX_OSS] = "Linux OSS"; - apiMap[RtAudio::RTAUDIO_DUMMY] = "RtAudio Dummy"; - - std::vector< RtAudio::Api > apis; - RtAudio::getCompiledApi(apis); - - qInfo(logAudio()) << "RtAudio Version " << QString::fromStdString(RtAudio::getVersion()); - - qInfo(logAudio()) << "Compiled APIs:"; - for (unsigned int i = 0; i < apis.size(); i++) { - qInfo(logAudio()) << " " << QString::fromStdString(apiMap[apis[i]]); - } - - RtAudio::DeviceInfo info; - - qInfo(logAudio()) << "Current API: " << QString::fromStdString(apiMap[audio->getCurrentApi()]); - - unsigned int devices = audio->getDeviceCount(); - qInfo(logAudio()) << "Found " << devices << " audio device(s) *=default"; - - for (unsigned int i = 1; i < devices; i++) { - info = audio->getDeviceInfo(i); - if (info.inputChannels > 0) { - qInfo(logAudio()) << (info.isDefaultInput ? "*" : " ") << "(" << i << ") Input Device : " << QString::fromStdString(info.name).toLocal8Bit(); - ui->audioInputCombo->addItem(QString::fromStdString(info.name).toLocal8Bit(), i); - ui->serverRXAudioInputCombo->addItem(QString::fromStdString(info.name).toLocal8Bit(), i); - - if (fm.boundingRect(QString::fromStdString(info.name)).width() > numCharsIn) - numCharsIn = fm.boundingRect(QString::fromStdString(info.name)).width(); - - if (info.isDefaultInput) { - defaultAudioInputName = QString::fromStdString(info.name).toLocal8Bit(); - } - } - if (info.outputChannels > 0) { - qInfo(logAudio()) << (info.isDefaultOutput ? "*" : " ") << "(" << i << ") Output Device : " << QString::fromStdString(info.name).toLocal8Bit(); - ui->audioOutputCombo->addItem(QString::fromStdString(info.name).toLocal8Bit(), i); - ui->serverTXAudioOutputCombo->addItem(QString::fromStdString(info.name).toLocal8Bit(), i); - - if (fm.boundingRect(QString::fromStdString(info.name)).width() > numCharsOut) - numCharsOut = fm.boundingRect(QString::fromStdString(info.name)).width(); - - if (info.isDefaultOutput) { - defaultAudioOutputName = QString::fromStdString(info.name).toLocal8Bit(); - } - } - } - - delete audio; - break; - } - + if (audioDev == Q_NULLPTR) { + audioDev = new audioDevices(prefs.audioSystem, QFontMetrics(ui->audioInputCombo->font())); } - // Make the audio comboboxes expand when clicked (only needed for Windows) - ui->audioInputCombo->setStyleSheet(QString("QComboBox QAbstractItemView {min-width: %1px;}").arg(numCharsIn+30)); - ui->audioOutputCombo->setStyleSheet(QString("QComboBox QAbstractItemView {min-width: %1px;}").arg(numCharsOut+30)); - ui->serverTXAudioOutputCombo->setStyleSheet(QString("QComboBox QAbstractItemView {min-width: %1px;}").arg(numCharsOut+30)); - ui->serverRXAudioInputCombo->setStyleSheet(QString("QComboBox QAbstractItemView {min-width: %1px;}").arg(numCharsIn+30)); + audioDev->setAudioType(prefs.audioSystem); + audioDev->enumerate(); - - // Stop blocking signals so we can set the current values + ui->audioInputCombo->blockSignals(true); + ui->audioInputCombo->clear(); + ui->audioInputCombo->addItems(audioDev->getInputs()); + ui->audioInputCombo->setCurrentIndex(-1); + ui->audioInputCombo->setStyleSheet(QString("QComboBox QAbstractItemView {min-width: %1px;}").arg(audioDev->getNumCharsIn() + 30)); ui->audioInputCombo->blockSignals(false); - ui->audioOutputCombo->blockSignals(false); - ui->serverTXAudioOutputCombo->blockSignals(false); - ui->serverRXAudioInputCombo->blockSignals(false); + ui->audioInputCombo->setCurrentIndex(audioDev->findInput("Client", txSetup.name)); + ui->audioOutputCombo->blockSignals(true); + ui->audioOutputCombo->clear(); + ui->audioOutputCombo->addItems(audioDev->getOutputs()); + ui->audioOutputCombo->setCurrentIndex(-1); + ui->audioOutputCombo->setStyleSheet(QString("QComboBox QAbstractItemView {min-width: %1px;}").arg(audioDev->getNumCharsOut() + 30)); + ui->audioOutputCombo->blockSignals(false); + ui->audioOutputCombo->setCurrentIndex(audioDev->findOutput("Client", rxSetup.name)); + + ui->serverTXAudioOutputCombo->blockSignals(true); + ui->serverTXAudioOutputCombo->clear(); + ui->serverTXAudioOutputCombo->addItems(audioDev->getOutputs()); + ui->serverTXAudioOutputCombo->setCurrentIndex(-1); + ui->serverTXAudioOutputCombo->setStyleSheet(QString("QComboBox QAbstractItemView {min-width: %1px;}").arg(audioDev->getNumCharsOut() + 30)); + ui->serverTXAudioOutputCombo->blockSignals(false); + + ui->serverRXAudioInputCombo->blockSignals(true); + ui->serverRXAudioInputCombo->clear(); + ui->serverRXAudioInputCombo->addItems(audioDev->getInputs()); + ui->serverRXAudioInputCombo->setCurrentIndex(-1); + ui->serverRXAudioInputCombo->setStyleSheet(QString("QComboBox QAbstractItemView {min-width: %1px;}").arg(audioDev->getNumCharsIn()+30)); + ui->serverRXAudioInputCombo->blockSignals(false); rxSetup.type = prefs.audioSystem; txSetup.type = prefs.audioSystem; - int audioInputIndex = ui->audioInputCombo->findText(txSetup.name); - if (audioInputIndex != -1) { - qInfo(logGui()) << "Found Audio Input Device: " << txSetup.name; - ui->audioInputCombo->setCurrentIndex(audioInputIndex); - } - else { - qWarning(logGui()) << "Audio Input Device: " << txSetup.name << "Not Found, trying to select default"; - audioInputIndex = ui->audioInputCombo->findText(defaultAudioInputName); - if (audioInputIndex != -1) { - ui->audioInputCombo->setCurrentIndex(audioInputIndex); - } - else { - qWarning(logGui()) << "Unable to select default input device,"<< defaultAudioInputName << " help....."; - } - - } - - int audioOutputIndex = ui->audioOutputCombo->findText(rxSetup.name.toLocal8Bit()); - if (audioOutputIndex != -1) { - qInfo(logGui()) << "Found Audio Output Device: " << rxSetup.name.toLocal8Bit(); - ui->audioOutputCombo->setCurrentIndex(audioOutputIndex); - } - else { - qWarning(logGui()) << "Audio output Device: " << rxSetup.name << "Not Found, trying to select default"; - audioOutputIndex = ui->audioOutputCombo->findText(defaultAudioOutputName.toLocal8Bit()); - if (audioOutputIndex != -1) { - ui->audioOutputCombo->setCurrentIndex(audioOutputIndex); - } - else { - qWarning(logGui()) << "Unable to select default output device," << defaultAudioOutputName.toLocal8Bit() << " help....."; - } - } - if (!serverConfig.rigs.isEmpty()) - { - if (serverConfig.enabled) - qInfo(logGui()) << "Got Server Audio Input: " << serverConfig.rigs.first()->rxAudioSetup.name.toLocal8Bit(); - serverConfig.rigs.first()->rxAudioSetup.type = prefs.audioSystem; serverConfig.rigs.first()->txAudioSetup.type = prefs.audioSystem; - ui->serverRXAudioInputCombo->setCurrentIndex(defaultAudioInputIndex); - int serverAudioInputIndex = ui->serverRXAudioInputCombo->findText(serverConfig.rigs.first()->rxAudioSetup.name.toLocal8Bit()); - if (serverAudioInputIndex != -1) { - ui->serverRXAudioInputCombo->setCurrentIndex(serverAudioInputIndex); - } - else { - if (serverConfig.enabled) - qWarning(logGui()) << "Server audio input NOT FOUND " << serverConfig.rigs.first()->rxAudioSetup.name.toLocal8Bit() << "not selecting default"; - } - - if (serverConfig.enabled) - qInfo(logGui()) << "Got Server Audio Output: " << serverConfig.rigs.first()->txAudioSetup.name.toLocal8Bit(); - - ui->serverTXAudioOutputCombo->setCurrentIndex(defaultAudioOutputIndex); - int serverAudioOutputIndex = ui->serverTXAudioOutputCombo->findText(serverConfig.rigs.first()->txAudioSetup.name.toLocal8Bit()); - if (serverAudioOutputIndex != -1) { - ui->serverTXAudioOutputCombo->setCurrentIndex(serverAudioOutputIndex); - } - else { - if (serverConfig.enabled) - qWarning(logGui()) << "Server audio output NOT FOUND " << serverConfig.rigs.first()->txAudioSetup.name.toLocal8Bit() << "not selecting default"; - } - + ui->serverRXAudioInputCombo->setCurrentIndex(audioDev->findInput("Server", serverConfig.rigs.first()->rxAudioSetup.name)); + ui->serverTXAudioOutputCombo->setCurrentIndex(audioDev->findOutput("Server", serverConfig.rigs.first()->txAudioSetup.name)); } + qDebug(logSystem()) << "Audio devices done."; } diff --git a/wfmain.h b/wfmain.h index 7f318b2..2ae5fd6 100644 --- a/wfmain.h +++ b/wfmain.h @@ -42,6 +42,7 @@ #include "colorprefs.h" #include "loggingwindow.h" #include "cluster.h" +#include "audiodevices.h" #include #include @@ -1050,6 +1051,7 @@ private: QList clusters; QMutex clusterMutex; QColor clusterColor; + audioDevices* audioDev = Q_NULLPTR; }; Q_DECLARE_METATYPE(struct rigCapabilities) diff --git a/wfview.pro b/wfview.pro index c476d1f..f9c4390 100644 --- a/wfview.pro +++ b/wfview.pro @@ -179,7 +179,8 @@ SOURCES += main.cpp\ tcpserver.cpp \ cluster.cpp \ database.cpp \ - aboutbox.cpp + aboutbox.cpp \ + audiodevices.cpp HEADERS += wfmain.h \ colorprefs.h \ @@ -220,7 +221,8 @@ HEADERS += wfmain.h \ cluster.h \ database.h \ aboutbox.h \ - wfviewtypes.h + wfviewtypes.h \ + audiodevices.h FORMS += wfmain.ui \ diff --git a/wfview.vcxproj b/wfview.vcxproj index 300b8ee..269332f 100644 --- a/wfview.vcxproj +++ b/wfview.vcxproj @@ -16,8 +16,7 @@ QtVS_v304 10.0.19041.0 10.0.19041.0 - $(MSBuildProjectDirectory)\QtMsBuild - + $(MSBuildProjectDirectory)\QtMsBuild v142 @@ -37,10 +36,7 @@ debug\ wfview - - - - + @@ -48,34 +44,8 @@ - - - - - - wfview-debug\ - debug\ - wfview - true - - - wfview-release\ - release\ - wfview - true - false - - - msvc2019 - core;xml;network;gui;multimedia;widgets;serialport;printsupport - - - msvc2019 - core;xml;network;gui;multimedia;widgets;serialport;printsupport - - - - + wfview-debug\debug\wfviewtruewfview-release\release\wfviewtruefalsemsvc2019core;xml;network;gui;multimedia;widgets;serialport;printsupportmsvc2019core;xml;network;gui;multimedia;widgets;serialport;printsupport + .;..\rtaudio;..\portaudio\include;..\qcustomplot;..\opus\include;..\eigen;..\r8brain-free-src;resampler;release;/include;%(AdditionalIncludeDirectories) @@ -87,16 +57,14 @@ Sync release\ MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.52";BUILD_WFVIEW;__WINDOWS_WASAPI__;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX="/usr/local";GITSHORT="103dc9c";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.54";BUILD_WFVIEW;__WINDOWS_WASAPI__;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX="/usr/local";GITSHORT="0d2d9ba";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) false - - + MultiThreadedDLL true true Level3 - true - + true ..\portaudio\msvc\Win32\Release\portaudio_x86.lib;ole32.lib;..\opus\win32\VS2015\Win32\Release\opus.lib;shell32.lib;%(AdditionalDependencies) ..\portaudio\msvc\Win32\Release;..\opus\win32\VS2015\Win32\Release;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) @@ -117,28 +85,9 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.52\";BUILD_WFVIEW;__WINDOWS_WASAPI__;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX=\"/usr/local\";GITSHORT=\"103dc9c\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_XML_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.54\";BUILD_WFVIEW;__WINDOWS_WASAPI__;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX=\"/usr/local\";GITSHORT=\"0d2d9ba\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_XML_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) - - msvc - ./$(Configuration)/moc_predefs.h - Moc'ing %(Identity)... - output - $(Configuration) - moc_%(Filename).cpp - - - default - Rcc'ing %(Identity)... - $(Configuration) - qrc_%(Filename).cpp - - - Uic'ing %(Identity)... - $(ProjectDir) - ui_%(Filename).h - - + msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h .;..\rtaudio;..\portaudio\include;..\qcustomplot;..\opus\include;..\eigen;..\r8brain-free-src;resampler;debug;/include;%(AdditionalIncludeDirectories) @@ -150,14 +99,13 @@ Sync debug\ Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.52";BUILD_WFVIEW;__WINDOWS_WASAPI__;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX="/usr/local";GITSHORT="103dc9c";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.54";BUILD_WFVIEW;__WINDOWS_WASAPI__;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX="/usr/local";GITSHORT="0d2d9ba";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) false MultiThreadedDebugDLL true true Level3 - true - + true ..\portaudio\msvc\Win32\Debug\portaudio_x86.lib;ole32.lib;..\opus\win32\VS2015\Win32\Debug\opus.lib;shell32.lib;%(AdditionalDependencies) ..\portaudio\msvc\Win32\Debug;..\opus\win32\VS2015\Win32\Debug;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) @@ -176,32 +124,14 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.52\";BUILD_WFVIEW;__WINDOWS_WASAPI__;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX=\"/usr/local\";GITSHORT=\"103dc9c\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_XML_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.54\";BUILD_WFVIEW;__WINDOWS_WASAPI__;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;EIGEN_MPL2_ONLY;EIGEN_DONT_VECTORIZE;EIGEN_VECTORIZE_SSE3;PREFIX=\"/usr/local\";GITSHORT=\"0d2d9ba\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_XML_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) - - msvc - ./$(Configuration)/moc_predefs.h - Moc'ing %(Identity)... - output - $(Configuration) - moc_%(Filename).cpp - - - default - Rcc'ing %(Identity)... - $(Configuration) - qrc_%(Filename).cpp - - - Uic'ing %(Identity)... - $(ProjectDir) - ui_%(Filename).h - - + msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h + @@ -236,71 +166,303 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document true @@ -317,23 +479,139 @@ release\moc_predefs.h;%(Outputs) true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -367,16 +645,30 @@ - resources - resources - + + + + + + + + + + resourcesresources - style - style - + + + + + + + + + + stylestyle @@ -390,9 +682,6 @@ - - - - + \ No newline at end of file diff --git a/wfview.vcxproj.filters b/wfview.vcxproj.filters index 74c1354..bfbad15 100644 --- a/wfview.vcxproj.filters +++ b/wfview.vcxproj.filters @@ -56,6 +56,9 @@ Source Files + + Source Files + Source Files @@ -160,6 +163,9 @@ Header Files + + Header Files + Header Files @@ -199,6 +205,9 @@ Header Files + + Header Files + Header Files @@ -226,6 +235,9 @@ Header Files + + Header Files + Header Files @@ -265,17 +277,81 @@ Header Files - + Header Files + + + + + + + + + + + + + + + + + + + + Generated Files Generated Files + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -435,6 +511,6 @@ - + \ No newline at end of file