| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- #include <QFileDialog>
- #include <QMessageBox>
- #include <QSettings>
- #include <QtGlobal>
- #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()));
- connect(ui->hrtfFileList, SIGNAL(itemSelectionChanged()), this, SLOT(updateHrtfRemoveButton()));
- 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));
- updatePeriodSizeSlider();
- }
- int periodcount = settings.value("periods").toInt();
- ui->periodCountEdit->clear();
- if(periodcount >= 2)
- {
- ui->periodCountEdit->insert(QString::number(periodcount));
- updatePeriodCountSlider();
- }
- 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);
- updateHrtfRemoveButton();
- 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<QListWidgetItem*> 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<QListWidgetItem*> selected = ui->hrtfFileList->selectedItems();
- foreach(QListWidgetItem *item, selected)
- delete item;
- }
- void MainWindow::updateHrtfRemoveButton()
- {
- ui->hrtfRemoveButton->setEnabled(ui->hrtfFileList->selectedItems().size() != 0);
- }
- void MainWindow::showEnabledBackendMenu(QPoint pt)
- {
- QMap<QAction*,QString> 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<QListWidgetItem*> selected = ui->enabledBackendList->selectedItems();
- foreach(QListWidgetItem *item, selected)
- delete item;
- }
- else if(gotAction != NULL)
- {
- QMap<QAction*,QString>::const_iterator iter = actionMap.find(gotAction);
- if(iter != actionMap.end())
- ui->enabledBackendList->addItem(iter.value());
- }
- }
- void MainWindow::showDisabledBackendMenu(QPoint pt)
- {
- QMap<QAction*,QString> 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<QListWidgetItem*> selected = ui->disabledBackendList->selectedItems();
- foreach(QListWidgetItem *item, selected)
- delete item;
- }
- else if(gotAction != NULL)
- {
- QMap<QAction*,QString>::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);
- }
|