From 144059b062bd357cdec27416010872f37ef69cba Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 23 Jun 2013 22:47:51 -0700 Subject: Add a configuration UI application Not complete, but it's a decent start. Some problems: * Only some otions are handled (backend-specific options in particular aren't handled). * Does not warn when quitting with unsaved changes. * Some options are missing tooltips. --- CMakeLists.txt | 30 +- utils/alsoft-config/main.cpp | 11 + utils/alsoft-config/mainwindow.cpp | 573 +++++++++++++++ utils/alsoft-config/mainwindow.h | 54 ++ utils/alsoft-config/mainwindow.ui | 1396 ++++++++++++++++++++++++++++++++++++ 5 files changed, 2063 insertions(+), 1 deletion(-) create mode 100644 utils/alsoft-config/main.cpp create mode 100644 utils/alsoft-config/mainwindow.cpp create mode 100644 utils/alsoft-config/mainwindow.h create mode 100644 utils/alsoft-config/mainwindow.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index 13f8e0a2..19d1dece 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ INCLUDE(CheckCSourceCompiles) INCLUDE(CheckTypeSize) -PROJECT(OpenAL C) +PROJECT(OpenAL) SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) @@ -865,6 +865,34 @@ IF(ALSOFT_UTILS) ARCHIVE DESTINATION "lib${LIB_SUFFIX}" ) MESSAGE(STATUS "Building utility programs") + + find_package(Qt4) + if(QT_FOUND) + include(${QT_USE_FILE}) + include_directories(${QT_QTCORE_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR} + ${QT_QTCORE_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR}) + + set(alsoft-config_SRCS utils/alsoft-config/main.cpp + utils/alsoft-config/mainwindow.cpp + ) + + set(alsoft-config_UIS utils/alsoft-config/mainwindow.ui) + QT4_WRAP_UI(UIS ${alsoft-config_UIS}) + + set(alsoft-config_MOCS utils/alsoft-config/mainwindow.h) + QT4_WRAP_CPP(MOCS ${alsoft-config_MOCS}) + + add_executable(alsoft-config ${alsoft-config_SRCS} ${UIS} ${RSCS} ${TRS} ${MOCS}) + target_link_libraries(alsoft-config ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) + + INSTALL(TARGETS alsoft-config + RUNTIME DESTINATION bin + LIBRARY DESTINATION "lib${LIB_SUFFIX}" + ARCHIVE DESTINATION "lib${LIB_SUFFIX}" + ) + message(STATUS "Building configuration program") + endif() + MESSAGE(STATUS "") ENDIF() diff --git a/utils/alsoft-config/main.cpp b/utils/alsoft-config/main.cpp new file mode 100644 index 00000000..9e2d83c8 --- /dev/null +++ b/utils/alsoft-config/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/utils/alsoft-config/mainwindow.cpp b/utils/alsoft-config/mainwindow.cpp new file mode 100644 index 00000000..e799c4fb --- /dev/null +++ b/utils/alsoft-config/mainwindow.cpp @@ -0,0 +1,573 @@ +#include +#include +#include +#include +#include "mainwindow.h" +#include "ui_mainwindow.h" + +namespace { +static const struct { + char backend_name[16]; + char menu_string[32]; +} backendMenuList[] = { +#ifdef Q_OS_WIN32 + { "mmdevapi", "Add MMDevAPI" }, + { "dsound", "Add DirectSound" }, + { "winmm", "Add Windows Multimedia" }, +#endif +#ifdef Q_OS_MAC + { "core", "Add CoreAudio" }, +#endif + { "pulse", "Add PulseAudio" }, +#ifdef Q_OS_UNIX + { "alsa", "Add ALSA" }, + { "oss", "Add OSS" }, + { "solaris", "Add Solaris" }, + { "sndio", "Add SndIO" }, + { "qsa", "Add QSA" }, +#endif + { "port", "Add PortAudio" }, + { "opensl", "Add OpenSL" }, + { "null", "Add Null Output" }, + { "wave", "Add Wave Writer" }, + { "", "" } +}; + +static QString getDefaultConfigName() +{ +#ifdef Q_OS_WIN32 + static const char fname[] = "alsoft.ini"; + QByteArray base = qgetenv("AppData"); +#else + static const char fname[] = "alsoft.conf"; + QByteArray base = qgetenv("XDG_CONFIG_HOME"); + if(base.isEmpty()) + { + base = qgetenv("HOME"); + if(base.isEmpty() == false) + base += "/.config"; + } +#endif + if(base.isEmpty() == false) + return base +'/'+ fname; + return fname; +} +} + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + mPeriodSizeValidator(NULL), + mPeriodCountValidator(NULL), + mSourceCountValidator(NULL), + mEffectSlotValidator(NULL), + mSourceSendValidator(NULL), + mSampleRateValidator(NULL), + mReverbBoostValidator(NULL) +{ + ui->setupUi(this); + + mPeriodSizeValidator = new QIntValidator(64, 8192, this); + ui->periodSizeEdit->setValidator(mPeriodSizeValidator); + mPeriodCountValidator = new QIntValidator(2, 16, this); + ui->periodCountEdit->setValidator(mPeriodCountValidator); + + mSourceCountValidator = new QIntValidator(0, 256, this); + ui->srcCountLineEdit->setValidator(mSourceCountValidator); + mEffectSlotValidator = new QIntValidator(0, 16, this); + ui->effectSlotLineEdit->setValidator(mEffectSlotValidator); + mSourceSendValidator = new QIntValidator(0, 4, this); + ui->srcSendLineEdit->setValidator(mSourceSendValidator); + mSampleRateValidator = new QIntValidator(8000, 192000, this); + ui->sampleRateCombo->lineEdit()->setValidator(mSampleRateValidator); + + mReverbBoostValidator = new QDoubleValidator(-12.0, +12.0, 1, this); + ui->reverbBoostEdit->setValidator(mReverbBoostValidator); + + connect(ui->actionLoad, SIGNAL(triggered()), this, SLOT(loadConfigFromFile())); + connect(ui->actionSave_As, SIGNAL(triggered()), this, SLOT(saveConfigAsFile())); + + connect(ui->applyButton, SIGNAL(clicked()), this, SLOT(saveCurrentConfig())); + + connect(ui->periodSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(updatePeriodSizeEdit(int))); + connect(ui->periodSizeEdit, SIGNAL(editingFinished()), this, SLOT(updatePeriodSizeSlider())); + connect(ui->periodCountSlider, SIGNAL(valueChanged(int)), this, SLOT(updatePeriodCountEdit(int))); + connect(ui->periodCountEdit, SIGNAL(editingFinished()), this, SLOT(updatePeriodCountSlider())); + + connect(ui->hrtfAddButton, SIGNAL(clicked()), this, SLOT(addHrtfFile())); + connect(ui->hrtfRemoveButton, SIGNAL(clicked()), this, SLOT(removeHrtfFile())); + + ui->enabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->enabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showEnabledBackendMenu(QPoint))); + + ui->disabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->disabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDisabledBackendMenu(QPoint))); + + connect(ui->reverbBoostSlider, SIGNAL(valueChanged(int)), this, SLOT(updateReverbBoostEdit(int))); + connect(ui->reverbBoostEdit, SIGNAL(textEdited(QString)), this, SLOT(updateReverbBoostSlider(QString))); + + loadConfig(getDefaultConfigName()); +} + +MainWindow::~MainWindow() +{ + delete ui; + delete mPeriodSizeValidator; + delete mPeriodCountValidator; + delete mSourceCountValidator; + delete mEffectSlotValidator; + delete mSourceSendValidator; + delete mSampleRateValidator; + delete mReverbBoostValidator; +} + +void MainWindow::loadConfigFromFile() +{ + QString fname = QFileDialog::getOpenFileName(this, tr("Select Files")); + if(fname.isEmpty() == false) + loadConfig(fname); +} + +void MainWindow::loadConfig(const QString &fname) +{ + QSettings settings(fname, QSettings::IniFormat); + + QString sampletype = settings.value("sample-type").toString(); + ui->sampleFormatCombo->setCurrentIndex(0); + if(sampletype.isEmpty() == false) + { + for(int i = 1;i < ui->sampleFormatCombo->count();i++) + { + QString item = ui->sampleFormatCombo->itemText(i); + if(item.startsWith(sampletype)) + { + ui->sampleFormatCombo->setCurrentIndex(i); + break; + } + } + } + + QString channelconfig = settings.value("channels").toString(); + ui->channelConfigCombo->setCurrentIndex(0); + if(channelconfig.isEmpty() == false) + { + for(int i = 1;i < ui->channelConfigCombo->count();i++) + { + QString item = ui->channelConfigCombo->itemText(i); + if(item.startsWith(channelconfig)) + { + ui->channelConfigCombo->setCurrentIndex(i); + break; + } + } + } + + QString srate = settings.value("frequency").toString(); + if(srate.isEmpty()) + ui->sampleRateCombo->setCurrentIndex(0); + else + { + ui->sampleRateCombo->lineEdit()->clear(); + ui->sampleRateCombo->lineEdit()->insert(srate); + } + + ui->srcCountLineEdit->clear(); + ui->srcCountLineEdit->insert(settings.value("sources").toString()); + ui->effectSlotLineEdit->clear(); + ui->effectSlotLineEdit->insert(settings.value("slots").toString()); + ui->srcSendLineEdit->clear(); + ui->srcSendLineEdit->insert(settings.value("sends").toString()); + + QString resampler = settings.value("resampler").toString().trimmed(); + if(resampler.isEmpty()) + ui->resamplerComboBox->setCurrentIndex(0); + else + { + for(int i = 1;i < ui->resamplerComboBox->count();i++) + { + QString item = ui->resamplerComboBox->itemText(i); + int end = item.indexOf(' '); + if(end < 0) end = item.size(); + if(resampler.size() == end && resampler.compare(item.leftRef(end), Qt::CaseInsensitive) == 0) + { + ui->resamplerComboBox->setCurrentIndex(i); + break; + } + } + } + + int periodsize = settings.value("period_size").toInt(); + ui->periodSizeEdit->clear(); + if(periodsize >= 64) + ui->periodSizeEdit->insert(QString::number(periodsize)); + + int periodcount = settings.value("periods").toInt(); + ui->periodCountEdit->clear(); + if(periodcount >= 2) + ui->periodCountEdit->insert(QString::number(periodcount)); + + QStringList disabledCpuExts = settings.value("disable-cpu-exts").toStringList(); + if(disabledCpuExts.size() == 1) + disabledCpuExts = disabledCpuExts[0].split(QChar(',')); + std::transform(disabledCpuExts.begin(), disabledCpuExts.end(), + disabledCpuExts.begin(), std::mem_fun_ref(&QString::trimmed)); + ui->disableSSECheckBox->setChecked(disabledCpuExts.contains("sse", Qt::CaseInsensitive)); + ui->disableSSE2CheckBox->setChecked(disabledCpuExts.contains("sse2", Qt::CaseInsensitive)); + ui->disableNeonCheckBox->setChecked(disabledCpuExts.contains("neon", Qt::CaseInsensitive)); + + if(settings.value("hrtf").toString() == QString()) + ui->hrtfEnableButton->setChecked(true); + else + { + if(settings.value("hrtf", true).toBool()) + ui->hrtfForceButton->setChecked(true); + else + ui->hrtfDisableButton->setChecked(true); + } + + QStringList hrtf_tables = settings.value("hrtf_tables").toStringList(); + if(hrtf_tables.size() == 1) + hrtf_tables = hrtf_tables[0].split(QChar(',')); + std::transform(hrtf_tables.begin(), hrtf_tables.end(), + hrtf_tables.begin(), std::mem_fun_ref(&QString::trimmed)); + ui->hrtfFileList->clear(); + ui->hrtfFileList->addItems(hrtf_tables); + + ui->enabledBackendList->clear(); + ui->disabledBackendList->clear(); + QStringList drivers = settings.value("drivers").toStringList(); + if(drivers.size() == 0) + ui->backendCheckBox->setChecked(true); + else + { + if(drivers.size() == 1) + drivers = drivers[0].split(QChar(',')); + std::transform(drivers.begin(), drivers.end(), + drivers.begin(), std::mem_fun_ref(&QString::trimmed)); + + bool lastWasEmpty = false; + foreach(const QString &backend, drivers) + { + lastWasEmpty = backend.isEmpty(); + if(!backend.startsWith(QChar('-')) && !lastWasEmpty) + ui->enabledBackendList->addItem(backend); + else if(backend.size() > 1) + ui->disabledBackendList->addItem(backend.right(backend.size()-1)); + } + ui->backendCheckBox->setChecked(lastWasEmpty); + } + + QString defaultreverb = settings.value("default-reverb").toString().toLower(); + ui->defaultReverbComboBox->setCurrentIndex(0); + if(defaultreverb.isEmpty() == false) + { + for(int i = 0;i < ui->defaultReverbComboBox->count();i++) + { + if(defaultreverb.compare(ui->defaultReverbComboBox->itemText(i).toLower()) == 0) + { + ui->defaultReverbComboBox->setCurrentIndex(i); + break; + } + } + } + + ui->emulateEaxCheckBox->setChecked(settings.value("reverb/emulate-eax", false).toBool()); + ui->reverbBoostEdit->clear(); + ui->reverbBoostEdit->insert(settings.value("reverb/boost").toString()); + + QStringList excludefx = settings.value("excludefx").toStringList(); + if(excludefx.size() == 1) + excludefx = excludefx[0].split(QChar(',')); + std::transform(excludefx.begin(), excludefx.end(), + excludefx.begin(), std::mem_fun_ref(&QString::trimmed)); + ui->disableEaxReverbCheck->setChecked(excludefx.contains("eaxreverb", Qt::CaseInsensitive)); + ui->disableStdReverbCheck->setChecked(excludefx.contains("reverb", Qt::CaseInsensitive)); + ui->disableChorusCheck->setChecked(excludefx.contains("chorus", Qt::CaseInsensitive)); + ui->disableDistortionCheck->setChecked(excludefx.contains("distortion", Qt::CaseInsensitive)); + ui->disableEchoCheck->setChecked(excludefx.contains("echo", Qt::CaseInsensitive)); + ui->disableEqualizerCheck->setChecked(excludefx.contains("equalizer", Qt::CaseInsensitive)); + ui->disableFlangerCheck->setChecked(excludefx.contains("flanger", Qt::CaseInsensitive)); + ui->disableModulatorCheck->setChecked(excludefx.contains("modulator", Qt::CaseInsensitive)); + ui->disableDedicatedCheck->setChecked(excludefx.contains("dedicated", Qt::CaseInsensitive)); +} + +void MainWindow::saveCurrentConfig() +{ + saveConfig(getDefaultConfigName()); + QMessageBox::information(this, tr("Information"), + tr("Applications using OpenAL need to be restarted for changes to take effect.")); +} + +void MainWindow::saveConfigAsFile() +{ + QString fname = QFileDialog::getOpenFileName(this, tr("Select Files")); + if(fname.isEmpty() == false) + saveConfig(fname); +} + +void MainWindow::saveConfig(const QString &fname) const +{ + QSettings settings(fname, QSettings::IniFormat); + + /* HACK: Compound any stringlist values into a comma-separated string. */ + QStringList allkeys = settings.allKeys(); + foreach(const QString &key, allkeys) + { + QStringList vals = settings.value(key).toStringList(); + if(vals.size() > 1) + settings.setValue(key, vals.join(QChar(','))); + } + + QString str = ui->sampleFormatCombo->currentText(); + str.truncate(str.indexOf('-')); + settings.setValue("sample-type", str.trimmed()); + + str = ui->channelConfigCombo->currentText(); + str.truncate(str.indexOf('-')); + settings.setValue("channels", str.trimmed()); + + uint rate = ui->sampleRateCombo->currentText().toUInt(); + if(rate == 0) + settings.setValue("frequency", QString()); + else + settings.setValue("frequency", rate); + + settings.setValue("period_size", ui->periodSizeEdit->text()); + settings.setValue("periods", ui->periodCountEdit->text()); + + settings.setValue("sources", ui->srcCountLineEdit->text()); + settings.setValue("slots", ui->effectSlotLineEdit->text()); + + if(ui->resamplerComboBox->currentIndex() == 0) + settings.setValue("resampler", QString()); + else + { + str = ui->resamplerComboBox->currentText(); + settings.setValue("resampler", str.split(' ').first().toLower()); + } + + QStringList strlist; + if(ui->disableSSECheckBox->isChecked()) + strlist.append("sse"); + if(ui->disableSSE2CheckBox->isChecked()) + strlist.append("sse2"); + if(ui->disableNeonCheckBox->isChecked()) + strlist.append("neon"); + settings.setValue("disable-cpu-exts", strlist.join(QChar(','))); + + if(ui->hrtfForceButton->isChecked()) + settings.setValue("hrtf", "true"); + else if(ui->hrtfDisableButton->isChecked()) + settings.setValue("hrtf", "false"); + else + settings.setValue("hrtf", QString()); + + strlist.clear(); + QList items = ui->hrtfFileList->findItems("*", Qt::MatchWildcard); + foreach(const QListWidgetItem *item, items) + strlist.append(item->text()); + settings.setValue("hrtf_tables", strlist.join(QChar(','))); + + strlist.clear(); + items = ui->enabledBackendList->findItems("*", Qt::MatchWildcard); + foreach(const QListWidgetItem *item, items) + strlist.append(item->text()); + items = ui->disabledBackendList->findItems("*", Qt::MatchWildcard); + foreach(const QListWidgetItem *item, items) + strlist.append(QChar('-')+item->text()); + if(strlist.size() == 0 && !ui->backendCheckBox->isChecked()) + strlist.append("-all"); + else if(ui->backendCheckBox->isChecked()) + strlist.append(QString()); + settings.setValue("drivers", strlist.join(QChar(','))); + + // TODO: Remove check when we can properly match global values. + if(ui->defaultReverbComboBox->currentIndex() == 0) + settings.setValue("default-reverb", QString()); + else + { + str = ui->defaultReverbComboBox->currentText().toLower(); + settings.setValue("default-reverb", str); + } + + if(ui->emulateEaxCheckBox->isChecked()) + settings.setValue("reverb/emulate-eax", "true"); + else + settings.setValue("reverb/emulate-eax", QString()/*"false"*/); + + // TODO: Remove check when we can properly match global values. + if(ui->reverbBoostSlider->sliderPosition() == 0) + settings.setValue("reverb/boost", QString()); + else + settings.setValue("reverb/boost", ui->reverbBoostEdit->text()); + + strlist.clear(); + if(ui->disableEaxReverbCheck->isChecked()) + strlist.append("eaxreverb"); + if(ui->disableStdReverbCheck->isChecked()) + strlist.append("reverb"); + if(ui->disableChorusCheck->isChecked()) + strlist.append("chorus"); + if(ui->disableDistortionCheck->isChecked()) + strlist.append("distortion"); + if(ui->disableEchoCheck->isChecked()) + strlist.append("echo"); + if(ui->disableEqualizerCheck->isChecked()) + strlist.append("equalizer"); + if(ui->disableFlangerCheck->isChecked()) + strlist.append("flanger"); + if(ui->disableModulatorCheck->isChecked()) + strlist.append("modulator"); + if(ui->disableDedicatedCheck->isChecked()) + strlist.append("dedicated"); + settings.setValue("excludefx", strlist.join(QChar(','))); + + /* Remove empty keys + * FIXME: Should only remove keys whose value matches the globally-specified value. + */ + allkeys = settings.allKeys(); + foreach(const QString &key, allkeys) + { + str = settings.value(key).toString(); + if(str == QString()) + settings.remove(key); + } +} + + +void MainWindow::updatePeriodSizeEdit(int size) +{ + ui->periodSizeEdit->clear(); + if(size >= 64) + { + size = (size+32)&~0x3f; + ui->periodSizeEdit->insert(QString::number(size)); + } +} + +void MainWindow::updatePeriodSizeSlider() +{ + int pos = ui->periodSizeEdit->text().toInt(); + if(pos >= 64) + { + if(pos > 8192) + pos = 8192; + ui->periodSizeSlider->setSliderPosition(pos); + } +} + +void MainWindow::updatePeriodCountEdit(int count) +{ + ui->periodCountEdit->clear(); + if(count >= 2) + ui->periodCountEdit->insert(QString::number(count)); +} + +void MainWindow::updatePeriodCountSlider() +{ + int pos = ui->periodCountEdit->text().toInt(); + if(pos < 2) + pos = 0; + else if(pos > 16) + pos = 16; + ui->periodCountSlider->setSliderPosition(pos); +} + + +void MainWindow::addHrtfFile() +{ + QStringList fnames = QFileDialog::getOpenFileNames(this, tr("Select Files"), QString(), + "HRTF Datasets(*.mhr);;All Files(*.*)"); + if(fnames.isEmpty() == false) + ui->hrtfFileList->addItems(fnames); +} + +void MainWindow::removeHrtfFile() +{ + QList selected = ui->hrtfFileList->selectedItems(); + foreach(QListWidgetItem *item, selected) + delete item; +} + +void MainWindow::showEnabledBackendMenu(QPoint pt) +{ + QMap actionMap; + + pt = ui->enabledBackendList->mapToGlobal(pt); + + QMenu ctxmenu; + QAction *removeAction = ctxmenu.addAction(QIcon::fromTheme("list-remove"), "Remove"); + if(ui->enabledBackendList->selectedItems().size() == 0) + removeAction->setEnabled(false); + ctxmenu.addSeparator(); + for(size_t i = 0;backendMenuList[i].backend_name[0];i++) + { + QAction *action = ctxmenu.addAction(backendMenuList[i].menu_string); + actionMap[action] = backendMenuList[i].backend_name; + if(ui->enabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0 || + ui->disabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0) + action->setEnabled(false); + } + + QAction *gotAction = ctxmenu.exec(pt); + if(gotAction == removeAction) + { + QList selected = ui->enabledBackendList->selectedItems(); + foreach(QListWidgetItem *item, selected) + delete item; + } + else if(gotAction != NULL) + { + QMap::const_iterator iter = actionMap.find(gotAction); + if(iter != actionMap.end()) + ui->enabledBackendList->addItem(iter.value()); + } +} + +void MainWindow::showDisabledBackendMenu(QPoint pt) +{ + QMap actionMap; + + pt = ui->disabledBackendList->mapToGlobal(pt); + + QMenu ctxmenu; + QAction *removeAction = ctxmenu.addAction(QIcon::fromTheme("list-remove"), "Remove"); + if(ui->disabledBackendList->selectedItems().size() == 0) + removeAction->setEnabled(false); + ctxmenu.addSeparator(); + for(size_t i = 0;backendMenuList[i].backend_name[0];i++) + { + QAction *action = ctxmenu.addAction(backendMenuList[i].menu_string); + actionMap[action] = backendMenuList[i].backend_name; + if(ui->disabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0 || + ui->enabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0) + action->setEnabled(false); + } + + QAction *gotAction = ctxmenu.exec(pt); + if(gotAction == removeAction) + { + QList selected = ui->disabledBackendList->selectedItems(); + foreach(QListWidgetItem *item, selected) + delete item; + } + else if(gotAction != NULL) + { + QMap::const_iterator iter = actionMap.find(gotAction); + if(iter != actionMap.end()) + ui->disabledBackendList->addItem(iter.value()); + } +} + +void MainWindow::updateReverbBoostEdit(int value) +{ + ui->reverbBoostEdit->clear(); + if(value != 0) + ui->reverbBoostEdit->insert(QString::number(value/10.0, 'f', 1)); +} + +void MainWindow::updateReverbBoostSlider(QString value) +{ + int pos = int(value.toFloat()*10.0f); + ui->reverbBoostSlider->setSliderPosition(pos); +} diff --git a/utils/alsoft-config/mainwindow.h b/utils/alsoft-config/mainwindow.h new file mode 100644 index 00000000..28e109a2 --- /dev/null +++ b/utils/alsoft-config/mainwindow.h @@ -0,0 +1,54 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private slots: + void saveCurrentConfig(); + + void saveConfigAsFile(); + void loadConfigFromFile(); + + void updatePeriodSizeEdit(int size); + void updatePeriodSizeSlider(); + void updatePeriodCountEdit(int size); + void updatePeriodCountSlider(); + + void addHrtfFile(); + void removeHrtfFile(); + + void showEnabledBackendMenu(QPoint pt); + void showDisabledBackendMenu(QPoint pt); + + void updateReverbBoostEdit(int size); + void updateReverbBoostSlider(QString value); + +private: + Ui::MainWindow *ui; + + QValidator *mPeriodSizeValidator; + QValidator *mPeriodCountValidator; + QValidator *mSourceCountValidator; + QValidator *mEffectSlotValidator; + QValidator *mSourceSendValidator; + QValidator *mSampleRateValidator; + QValidator *mReverbBoostValidator; + + void loadConfig(const QString &fname); + void saveConfig(const QString &fname) const; +}; + +#endif // MAINWINDOW_H diff --git a/utils/alsoft-config/mainwindow.ui b/utils/alsoft-config/mainwindow.ui new file mode 100644 index 00000000..1344554f --- /dev/null +++ b/utils/alsoft-config/mainwindow.ui @@ -0,0 +1,1396 @@ + + + MainWindow + + + + 0 + 0 + 564 + 473 + + + + OpenAL Soft Configuration + + + + + + + + + 470 + 405 + 81 + 25 + + + + Apply + + + + + + + + + 10 + 0 + 541 + 401 + + + + 0 + + + + Playback + + + + + 120 + 20 + 206 + 23 + + + + The output sample type. Currently, all mixing is done with 32-bit +float and converted to the output sample type as needed. + + + QComboBox::AdjustToContents + + + + - Autodetect - + + + + + int8 - signed 8-bit int + + + + + uint8 - unsigned 8-bit int + + + + + int16 - signed 16-bit int + + + + + uint16 - unsigned 16-bit int + + + + + int32 - signed 32-bit int + + + + + uint32 - unsigned 32-bit int + + + + + float32 - 32-bit float + + + + + + + 10 + 20 + 101 + 21 + + + + Sample Format: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 10 + 50 + 101 + 21 + + + + Channels: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 120 + 50 + 247 + 23 + + + + The output channel configuration. Note that not all backends +can properly detect the channel configuration and may default +to stereo output. + + + QComboBox::AdjustToContents + + + + - Autodetect - + + + + + mono - 1-channel Mono + + + + + stereo - 2-channel Stereo + + + + + quad - 4-channel Quadraphonic + + + + + surround51 - 5.1 Surround Sound + + + + + surround61 - 6.1 Surround Sound + + + + + surround71 - 7.1 Surround Sound + + + + + + + 120 + 80 + 123 + 22 + + + + The playback/mixing sample rate. + + + true + + + QComboBox::NoInsert + + + QComboBox::AdjustToContents + + + + - Autodetect - + + + + + 96000 + + + + + 48000 + + + + + 44100 + + + + + 32000 + + + + + 22050 + + + + + 16000 + + + + + 11025 + + + + + 8000 + + + + + + + 10 + 80 + 101 + 21 + + + + Sample Rate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 10 + 200 + 511 + 161 + + + + HRTF (Stereo only) + + + + + 20 + 30 + 71 + 21 + + + + Allows applications to request HRTF mixing. + + + Enable + + + true + + + + + + 20 + 50 + 71 + 21 + + + + Does not allow HRTF mixing, even when requested. + + + Disable + + + + + + 20 + 70 + 71 + 21 + + + + Attempts to force HRTF mixing, even if applications request not +to do it. This may override the channel configuration and +sample rate. + + + Force + + + + + + 110 + 30 + 361 + 121 + + + + A list of files containing HRTF data sets. The listed data sets +are used in place of or in addiiton to the the built-in set. The +filenames may contain these markers, which will be replaced +as needed: +%r - Device sampling rate +%% - Percent sign (%) + + + false + + + QAbstractItemView::InternalMove + + + true + + + QAbstractItemView::ExtendedSelection + + + Qt::ElideNone + + + + + + 475 + 30 + 25 + 25 + + + + + + + + + + + + false + + + + + + 475 + 60 + 25 + 25 + + + + + + + + + + + + + + + + 10 + 110 + 511 + 91 + + + + Buffer Metrics + + + + + 260 + 20 + 241 + 51 + + + + The number of update periods. Higher values create a larger +mix ahead, which helps protect against skips when the CPU is +under load, but increases the delay between a sound getting +mixed and being heard. + + + + + 20 + 0 + 201 + 21 + + + + Period Count + + + Qt::AlignCenter + + + + + + 70 + 20 + 160 + 23 + + + + 1 + + + 16 + + + 1 + + + 2 + + + 1 + + + true + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 1 + + + + + + 20 + 20 + 51 + 22 + + + + 4 + + + + + + + 10 + 20 + 241 + 51 + + + + The update period size, in sample frames. This is the number of +frames needed for each mixing update. + + + + + 60 + 20 + 160 + 23 + + + + 0 + + + 8192 + + + 64 + + + 1024 + + + 0 + + + true + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 512 + + + + + + 10 + 0 + 201 + 21 + + + + Period Samples + + + Qt::AlignCenter + + + + + + 10 + 20 + 51 + 22 + + + + 1024 + + + + + + + + Resources + + + + + 190 + 20 + 51 + 22 + + + + The maximum number of allocatable sources. Lower values may +help for systems with apps that try to play more sounds than +the CPU can handle. + + + + + + 3 + + + true + + + 256 + + + + + + 10 + 20 + 171 + 21 + + + + Number of Sound Sources: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 10 + 50 + 171 + 21 + + + + Number of Effect Slots: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 190 + 50 + 51 + 22 + + + + The maximum number of Auxiliary Effect Slots an app can +create. A slot can use a non-negligible amount of CPU time if +an effect is set on it even if no sources are feeding it, so this +may help when apps use more than the system can handle. + + + + + + 1 + + + true + + + 4 + + + + + + 10 + 80 + 171 + 21 + + + + Number of Source Sends: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 190 + 80 + 51 + 22 + + + + The number of auxiliary sends per source. When not specified, +it allows the app to request how many it wants. The maximum +value currently possible is 4. + + + 1 + + + Auto + + + + + + 30 + 120 + 71 + 21 + + + + Resampler: + + + + + + 110 + 120 + 203 + 23 + + + + The resampling method used when mixing sources. + + + QComboBox::AdjustToContents + + + + - Default - + + + + + Point (low quality, fast) + + + + + Linear (basic quality, fast) + + + + + Cubic Spline (good quality) + + + + + + + 10 + 150 + 511 + 61 + + + + Disables use of specific CPU extensions. Certain methods may +utilize CPU extensions when detected, and this is useful for +preventing those extensions from being used. + + + CPU Extensions + + + + + 10 + 20 + 101 + 31 + + + + Disable SSE + + + + + + 200 + 20 + 111 + 31 + + + + Disable SSE2 + + + + + + 380 + 20 + 111 + 31 + + + + Disable Neon + + + + + + + Backends + + + + + 170 + 200 + 161 + 21 + + + + When checked, allows all other available backends not listed in the priority or disabled lists. + + + Allow Other Backends + + + true + + + + + + 40 + 40 + 191 + 151 + + + + The backend driver list order. Unknown backends and +duplicated names are ignored. + + + QAbstractItemView::InternalMove + + + + + + 40 + 20 + 191 + 20 + + + + Priority Backends: + + + + + + 270 + 40 + 191 + 151 + + + + Disabled backend driver list. + + + + + + 270 + 20 + 191 + 20 + + + + Disabled Backends: + + + + + + Effects + + + + + 10 + 60 + 161 + 21 + + + + Uses a simpler reverb method to emulate the EAX reverb +effect. This may slightly improve performance at the cost of +some quality. + + + Qt::RightToLeft + + + Emulate EAX Reverb: + + + + + + 10 + 100 + 511 + 61 + + + + Global amplification for reverb output, expressed in decibels. ++6 will be a scale of (approximately) 2x, +12 will be a scale of +4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A +value of 0 means no change. + + + Reverb Boost + + + + + 10 + 30 + 391 + 23 + + + + + + + -120 + + + 120 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + + + + 410 + 30 + 51 + 22 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0.0 + + + + + + 460 + 30 + 31 + 21 + + + + dB + + + + + + + 9 + 170 + 511 + 181 + + + + Disables effects, preventing apps from recognizing them. This +can help for apps that try to use effects which are too CPU +intensive for the system to handle. + + + Disabled Effects + + + + + 70 + 30 + 131 + 21 + + + + EAX Reverb + + + + + + 70 + 60 + 131 + 21 + + + + Standard Reverb + + + + + + 70 + 90 + 131 + 21 + + + + Chorus + + + + + + 70 + 120 + 131 + 21 + + + + Distortion + + + + + + 70 + 150 + 131 + 21 + + + + Echo + + + + + + 320 + 30 + 131 + 21 + + + + Equalizer + + + + + + 320 + 60 + 131 + 21 + + + + Flanger + + + + + + 320 + 90 + 131 + 21 + + + + Ring Modulator + + + + + + 320 + 120 + 131 + 21 + + + + Disables both the Dedicated Dialog and Dedicated LFE effects +added by the ALC_EXT_DEDICATED extension. + + + Dedicated ... + + + + + + + 10 + 20 + 141 + 21 + + + + Default Reverb Effect: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 160 + 20 + 142 + 23 + + + + QComboBox::AdjustToContents + + + + None + + + + + Generic + + + + + PaddedCell + + + + + Room + + + + + Bathroom + + + + + Livingroom + + + + + Stoneroom + + + + + Auditorium + + + + + ConcertHall + + + + + Cave + + + + + Arena + + + + + Hangar + + + + + CarpetedHallway + + + + + Hallway + + + + + StoneCorridor + + + + + Alley + + + + + Forest + + + + + City + + + + + Mountains + + + + + Quarry + + + + + Plain + + + + + ParkingLot + + + + + SewerPipe + + + + + Underwater + + + + + Drugged + + + + + Dizzy + + + + + Psychotic + + + + + + + + + + 0 + 0 + 564 + 20 + + + + + &File + + + + + + + + + + + TopToolBarArea + + + false + + + + + + + + + &Quit + + + + + + + + Save &As... + + + Save Configuration As + + + + + + + + &Load... + + + Load Configuration File + + + + + + + + actionQuit + activated() + MainWindow + close() + + + -1 + -1 + + + 267 + 181 + + + + + + ShowHRTFContextMenu(QPoint) + + -- cgit v1.2.3