From 6d568d07b31ba2ae39703cfd272d3003ea542018 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Sun, 19 Apr 2020 23:36:48 +0800 Subject: Legacy code massacre! Complete reconstruction of the settings infrastructure. All options are now registered using a revamped option API. Legacy configuration files are no longer compatible. Please make a backup. --- qmidiplayer-desktop/CMakeLists.txt | 2 + qmidiplayer-desktop/main.cpp | 1 + qmidiplayer-desktop/qmpchannelswindow.cpp | 76 +- qmidiplayer-desktop/qmpchannelswindow.hpp | 3 + qmidiplayer-desktop/qmpcustomizewindow.cpp | 47 +- qmidiplayer-desktop/qmpcustomizewindow.hpp | 11 +- qmidiplayer-desktop/qmpdeviceprioritydialog.cpp | 28 +- qmidiplayer-desktop/qmpdeviceprioritydialog.hpp | 10 +- qmidiplayer-desktop/qmpdevpropdialog.cpp | 57 +- qmidiplayer-desktop/qmpdevpropdialog.hpp | 7 +- qmidiplayer-desktop/qmpefxwindow.cpp | 76 +- qmidiplayer-desktop/qmpinfowindow.cpp | 10 +- qmidiplayer-desktop/qmpmainwindow.cpp | 179 ++-- qmidiplayer-desktop/qmpmainwindow.hpp | 8 +- qmidiplayer-desktop/qmpplistwindow.cpp | 45 +- qmidiplayer-desktop/qmpplistwindow.hpp | 2 + qmidiplayer-desktop/qmpplugin.cpp | 47 +- qmidiplayer-desktop/qmpplugin.hpp | 7 + qmidiplayer-desktop/qmppresetselect.cpp | 6 +- qmidiplayer-desktop/qmpsettings.cpp | 233 +++++ qmidiplayer-desktop/qmpsettings.hpp | 88 ++ qmidiplayer-desktop/qmpsettingswindow.cpp | 1051 ++++++++++------------- qmidiplayer-desktop/qmpsettingswindow.hpp | 71 +- qmidiplayer-desktop/qmpsettingswindow.ui | 741 +--------------- qmidiplayer-desktop/translations/qmp_zh_CN.ts | 371 ++------ 25 files changed, 1229 insertions(+), 1948 deletions(-) create mode 100644 qmidiplayer-desktop/qmpsettings.cpp create mode 100644 qmidiplayer-desktop/qmpsettings.hpp (limited to 'qmidiplayer-desktop') diff --git a/qmidiplayer-desktop/CMakeLists.txt b/qmidiplayer-desktop/CMakeLists.txt index 9d285c3..c34f258 100644 --- a/qmidiplayer-desktop/CMakeLists.txt +++ b/qmidiplayer-desktop/CMakeLists.txt @@ -13,6 +13,7 @@ set(qmpdesktop_SOURCES qmpplugin.hpp qmppresetselect.hpp qmpsettingswindow.hpp + qmpsettings.hpp main.cpp qdialskulpturestyle.cpp qmpchanneleditor.cpp @@ -28,6 +29,7 @@ set(qmpdesktop_SOURCES qmpplugin.cpp qmppresetselect.cpp qmpsettingswindow.cpp + qmpsettings.cpp qmpchanneleditor.ui qmpchannelswindow.ui qmpcustomizewindow.ui diff --git a/qmidiplayer-desktop/main.cpp b/qmidiplayer-desktop/main.cpp index 9f1d593..6bf21c0 100644 --- a/qmidiplayer-desktop/main.cpp +++ b/qmidiplayer-desktop/main.cpp @@ -37,6 +37,7 @@ int main(int argc,char **argv) QCoreApplication::setApplicationVersion(APP_VERSION); if(!qgetenv("QT_SCALE_FACTOR").length()&&!qgetenv("QT_SCREEN_SCALE_FACTORS").length()) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + qSetMessagePattern("%{time} @ %{file} : %{line}, in %{function} : %{message}"); QApplication a(argc,argv); QTranslator qtTranslator; diff --git a/qmidiplayer-desktop/qmpchannelswindow.cpp b/qmidiplayer-desktop/qmpchannelswindow.cpp index 41f545e..0854e4c 100644 --- a/qmidiplayer-desktop/qmpchannelswindow.cpp +++ b/qmidiplayer-desktop/qmpchannelswindow.cpp @@ -236,8 +236,9 @@ qmpChannelsWindow::qmpChannelsWindow(QWidget *parent) : ui(new Ui::qmpChannelsWindow) { ui->setupUi(this); + mainwindow=qmpMainWindow::getInstance(); ui->tvChannels->setHorizontalHeader(new QHeaderView(Qt::Orientation::Horizontal)); - ui->tvChannels->setModel(chmodel=new qmpChannelsModel); + ui->tvChannels->setModel(chmodel=new qmpChannelsModel(ui->tvChannels)); ui->tvChannels->setItemDelegateForColumn(3,new qmpDeviceItemDelegate(false,ui->tvChannels)); ui->tvChannels->setAlternatingRowColors(true); ui->tvChannels->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); @@ -268,25 +269,6 @@ qmpChannelsWindow::qmpChannelsWindow(QWidget *parent) : emit this->noteOn(); } ,nullptr,false); - std::vector devs=qmpMainWindow::getInstance()->getPlayer()->getMidiOutDevices(); - size_t devc=devs.size(); - std::set devset; - for(auto dev:devs)devset.insert(dev); - std::string selecteddev; - for(auto setdev:qmpSettingsWindow::getSettingsIntf()->value("Midi/DevicePriority",QList{"Internal FluidSynth"}).toList()) - if(devset.find(setdev.toString().toStdString())!=devset.end()) - { - selecteddev=setdev.toString().toStdString(); - break; - } - for(int ch=0;ch<16;++ch) - { - for(size_t j=0;jgetPlayer()->setChannelOutput(ch,j); - } - } qmpMainWindow::getInstance()->registerFunctionality( chnlf=new qmpChannelFunc(this), std::string("Channel"), @@ -295,42 +277,68 @@ qmpChannelsWindow::qmpChannelsWindow(QWidget *parent) : 0, true ); - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) - setGeometry(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlW",QRect(-999,-999,999,999)).toRect()); - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlWShown",0).toInt()) + if(mainwindow->getSettings()->getOptionRaw("DialogStatus/ChnlW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) + setGeometry(mainwindow->getSettings()->getOptionRaw("DialogStatus/ChnlW",QRect(-999,-999,999,999)).toRect()); + if(mainwindow->getSettings()->getOptionRaw("DialogStatus/ChnlWShown",0).toInt()) {show();qmpMainWindow::getInstance()->setFuncState("Channel",true);} } void qmpChannelsWindow::showEvent(QShowEvent *event) { - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + if(mainwindow->getSettings()->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlWShown",1); + mainwindow->getSettings()->setOptionRaw("DialogStatus/ChnlWShown",1); } - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) - setGeometry(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/ChnlW",QRect(-999,-999,999,999)).toRect()); + if(mainwindow->getSettings()->getOptionRaw("DialogStatus/ChnlW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) + setGeometry(mainwindow->getSettings()->getOptionRaw("DialogStatus/ChnlW",QRect(-999,-999,999,999)).toRect()); event->accept(); } void qmpChannelsWindow::closeEvent(QCloseEvent *event) { - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + if(mainwindow->getSettings()->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlW",geometry()); + mainwindow->getSettings()->setOptionRaw("DialogStatus/ChnlW",geometry()); } setVisible(false); - if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + if(!qmpMainWindow::getInstance()->isFinalizing()&&mainwindow->getSettings()->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/ChnlWShown",0); + mainwindow->getSettings()->setOptionRaw("DialogStatus/ChnlWShown",0); } - qmpMainWindow::getInstance()->setFuncState("Channel",false); + mainwindow->setFuncState("Channel",false); event->accept(); } +void qmpChannelsWindow::selectDefaultDevice() +{ + std::string selecteddev; + std::vector devs=mainwindow->getPlayer()->getMidiOutDevices(); + size_t devc=devs.size(); + std::set devset; + for(auto dev:devs)devset.insert(dev); + QVariant *devpriov=static_cast(qmpMainWindow::getInstance()->getSettings()->getOptionCustom("Midi/DevicePriority")); + QList devprio=devpriov->toList(); + delete devpriov; + for(auto &setdev:devprio) + if(devset.find(setdev.toString().toStdString())!=devset.end()) + { + selecteddev=setdev.toString().toStdString(); + break; + } + for(int ch=0;ch<16;++ch) + { + for(size_t j=0;jgetPlayer()->setChannelOutput(ch,j); + } + } +} + qmpChannelsWindow::~qmpChannelsWindow() { - qmpMainWindow::getInstance()->unregisterFunctionality("Channel"); - qmpMainWindow::getInstance()->getPlayer()->unregisterEventHandler(eh); + mainwindow->unregisterFunctionality("Channel"); + mainwindow->getPlayer()->unregisterEventHandler(eh); delete chnlf; delete chi;delete cha; delete ui; diff --git a/qmidiplayer-desktop/qmpchannelswindow.hpp b/qmidiplayer-desktop/qmpchannelswindow.hpp index 072f9d3..f78d032 100644 --- a/qmidiplayer-desktop/qmpchannelswindow.hpp +++ b/qmidiplayer-desktop/qmpchannelswindow.hpp @@ -20,6 +20,7 @@ namespace Ui { } class qmpChannelsWindow; +class qmpMainWindow; class qmpChannelFunc:public qmpFuncBaseIntf { @@ -78,6 +79,7 @@ class qmpChannelsWindow:public QWidget ~qmpChannelsWindow(); void showEvent(QShowEvent *event); void closeEvent(QCloseEvent *event); + void selectDefaultDevice(); public slots: void showChannelEditorWindow(int chid); void on_pbUnmute_clicked(); @@ -87,6 +89,7 @@ class qmpChannelsWindow:public QWidget void noteOn(); private: + qmpMainWindow* mainwindow; Ui::qmpChannelsWindow *ui; qmpPresetSelector *pselectw; qmpChannelEditor *ceditw; diff --git a/qmidiplayer-desktop/qmpcustomizewindow.cpp b/qmidiplayer-desktop/qmpcustomizewindow.cpp index a2ff19c..0ea3228 100644 --- a/qmidiplayer-desktop/qmpcustomizewindow.cpp +++ b/qmidiplayer-desktop/qmpcustomizewindow.cpp @@ -8,24 +8,11 @@ #include "qmpcustomizewindow.hpp" #include "ui_qmpcustomizewindow.h" -qmpCustomizeWindow::qmpCustomizeWindow(QWidget *parent) : +qmpCustomizeWindow::qmpCustomizeWindow(QWidget *parent): QDialog(parent), ui(new Ui::qmpCustomizeWindow) { ui->setupUi(this); - QSettings *s=qmpMainWindow::getInstance()->getSettingsWindow()->getSettingsIntf(); - QList defa={"FileInfo","Render","Panic","ReloadSynth"}; - QList defb={"Channel","Playlist","Effects","Visualization"}; - QList a=s->value("Behavior/Actions",QVariant(defa)).toList(); - QList b=s->value("Behavior/Toolbar",QVariant(defb)).toList(); - std::vector& v=qmpMainWindow::getInstance()->getWidgets(1); - v.clear(); - for(int i=0;i& vv=qmpMainWindow::getInstance()->getWidgets(0); - vv.clear(); - for(int i=0;ilwAvail->clear(); ui->lwEnabled->clear(); - ow=w; - std::vector& v=qmpMainWindow::getInstance()->getWidgets(w); + QList list=static_cast(data)->toList(); + std::vector v; + for(auto i:list) + v.push_back(i.toString().toStdString()); std::map& m=qmpMainWindow::getInstance()->getFunc(); std::set s; for(auto i=v.begin();i!=v.end();++i) @@ -67,6 +55,16 @@ void qmpCustomizeWindow::launch(int w) } } +void *qmpCustomizeWindow::save() +{ + QList ret; + for(int i=0;ilwEnabled->count();++i) + { + ret.push_back(QVariant(ui->lwEnabled->item(i)->toolTip())); + } + return new QVariant(ret); +} + void qmpCustomizeWindow::on_tbAdd_clicked() { if(!ui->lwAvail->currentItem())return; @@ -82,21 +80,12 @@ void qmpCustomizeWindow::on_tbRemove_clicked() void qmpCustomizeWindow::on_buttonBox_accepted() { - std::vector& v=qmpMainWindow::getInstance()->getWidgets(ow); - v.clear(); - QList ql; - for(int i=0;ilwEnabled->count();++i) - { - v.push_back(ui->lwEnabled->item(i)->toolTip().toStdString()); - ql.push_back(QVariant(ui->lwEnabled->item(i)->toolTip())); - } - QSettings *s=qmpMainWindow::getInstance()->getSettingsWindow()->getSettingsIntf(); - s->setValue(ow?"Behavior/Actions":"Behavior/Toolbar",ql); - qmpMainWindow::getInstance()->setupWidget(); + accept(); close(); } void qmpCustomizeWindow::on_buttonBox_rejected() { + reject(); close(); } diff --git a/qmidiplayer-desktop/qmpcustomizewindow.hpp b/qmidiplayer-desktop/qmpcustomizewindow.hpp index 0d0f529..321c22e 100644 --- a/qmidiplayer-desktop/qmpcustomizewindow.hpp +++ b/qmidiplayer-desktop/qmpcustomizewindow.hpp @@ -7,27 +7,24 @@ namespace Ui { class qmpCustomizeWindow; } -class qmpCustomizeWindow : public QDialog +class qmpCustomizeWindow:public QDialog { Q_OBJECT public: - explicit qmpCustomizeWindow(QWidget *parent = 0); + explicit qmpCustomizeWindow(QWidget *parent=nullptr); ~qmpCustomizeWindow(); - void launch(int w); + void load(void* data); + void* save(); private slots: void on_tbAdd_clicked(); - void on_tbRemove_clicked(); - void on_buttonBox_accepted(); - void on_buttonBox_rejected(); private: Ui::qmpCustomizeWindow *ui; - int ow; }; #endif // QMPCUSTOMIZEWINDOW_HPP diff --git a/qmidiplayer-desktop/qmpdeviceprioritydialog.cpp b/qmidiplayer-desktop/qmpdeviceprioritydialog.cpp index d26fb45..bf358d8 100644 --- a/qmidiplayer-desktop/qmpdeviceprioritydialog.cpp +++ b/qmidiplayer-desktop/qmpdeviceprioritydialog.cpp @@ -16,7 +16,6 @@ qmpDevicePriorityDialog::qmpDevicePriorityDialog(QWidget *parent) : ui->tvDevices->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::ResizeToContents); ui->tvDevices->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows); model->setHorizontalHeaderLabels({"E","Device","Connected?"}); - setdevs=qmpSettingsWindow::getSettingsIntf()->value("Midi/DevicePriority",QList{"Internal FluidSynth"}).toList(); } qmpDevicePriorityDialog::~qmpDevicePriorityDialog() @@ -30,6 +29,7 @@ void qmpDevicePriorityDialog::setupRegisteredDevices() auto conndevs=CMidiPlayer::getInstance()->getMidiOutDevices(); for(auto dev:conndevs) sconn.insert(dev); + model->removeRows(0,model->rowCount()); for(auto dev:setdevs) { QStandardItem *e=new QStandardItem; @@ -60,6 +60,21 @@ void qmpDevicePriorityDialog::setupRegisteredDevices() } } +void qmpDevicePriorityDialog::load(void *data) +{ + setdevs=static_cast(data)->toList(); + setupRegisteredDevices(); +} + +void *qmpDevicePriorityDialog::save() +{ + QList ret; + for(int i=0;irowCount();++i) + if(model->item(i,0)->checkState()==Qt::CheckState::Checked) + ret.push_back(model->item(i,1)->text()); + return new QVariant(ret); +} + void qmpDevicePriorityDialog::on_pbUp_clicked() { const QModelIndex &idx=ui->tvDevices->selectionModel()->currentIndex(); @@ -88,9 +103,10 @@ void qmpDevicePriorityDialog::on_pbDown_clicked() void qmpDevicePriorityDialog::on_buttonBox_accepted() { - QList setdevs; - for(int i=0;irowCount();++i) - if(model->item(i,0)->checkState()==Qt::CheckState::Checked) - setdevs.push_back(model->item(i,1)->text()); - qmpSettingsWindow::getSettingsIntf()->setValue("Midi/DevicePriority",setdevs); + accept(); +} + +void qmpDevicePriorityDialog::on_buttonBox_rejected() +{ + reject(); } diff --git a/qmidiplayer-desktop/qmpdeviceprioritydialog.hpp b/qmidiplayer-desktop/qmpdeviceprioritydialog.hpp index d48a2aa..78ce3fa 100644 --- a/qmidiplayer-desktop/qmpdeviceprioritydialog.hpp +++ b/qmidiplayer-desktop/qmpdeviceprioritydialog.hpp @@ -9,24 +9,28 @@ namespace Ui { class qmpDevicePriorityDialog; } -class qmpDevicePriorityDialog : public QDialog +class qmpDevicePriorityDialog:public QDialog { Q_OBJECT public: explicit qmpDevicePriorityDialog(QWidget *parent=nullptr); ~qmpDevicePriorityDialog(); - void setupRegisteredDevices(); + void load(void* data); + void* save(); private slots: void on_pbUp_clicked(); void on_pbDown_clicked(); void on_buttonBox_accepted(); -private: + void on_buttonBox_rejected(); + + private: Ui::qmpDevicePriorityDialog *ui; QStandardItemModel *model; QList setdevs; + void setupRegisteredDevices(); }; #endif // QMPDEVICEPRIORITYDIALOG_HPP diff --git a/qmidiplayer-desktop/qmpdevpropdialog.cpp b/qmidiplayer-desktop/qmpdevpropdialog.cpp index 64c385d..3b9ccc4 100644 --- a/qmidiplayer-desktop/qmpdevpropdialog.cpp +++ b/qmidiplayer-desktop/qmpdevpropdialog.cpp @@ -21,15 +21,19 @@ qmpDevPropDialog::qmpDevPropDialog(QWidget *parent) : this->ui->twProps->edit(ui->twProps->model()->index(r,c)); if(c==3) { - QString p=QFileDialog::getOpenFileUrl(this,"Select Device Initialization File",QUrl()).toLocalFile(); + QString p=QFileDialog::getOpenFileUrl(this,tr("Select Device Initialization File"),QUrl()).toLocalFile(); if(p.length())this->ui->twProps->item(r,2)->setText(p); } }); connect(ui->twProps,&QTableWidget::cellChanged,this,[this](int r,int c){ if(c!=0)return; - QString connst("Disconnected"); + QString connst(tr("Disconnected")); for(auto&ds:qmpMainWindow::getInstance()->getPlayer()->getMidiOutDevices()) - if(ui->twProps->item(r,c)->text()==QString::fromStdString(ds)){connst="Connected";break;} + if(ui->twProps->item(r,c)->text()==QString::fromStdString(ds)) + { + connst=tr("Connected"); + break; + } ui->twProps->item(r,1)->setText(connst); }); } @@ -39,16 +43,31 @@ qmpDevPropDialog::~qmpDevPropDialog() delete ui; } -void qmpDevPropDialog::launch() +void qmpDevPropDialog::load(void *data) { - QSettings *s=qmpSettingsWindow::getSettingsIntf(); + QList lst=static_cast(data)->toList(); ui->twProps->clearContents(); ui->twProps->setRowCount(0); - s->beginGroup("DevInit"); - for(auto&k:s->allKeys()) - setupRow(k,s->value(k).toString()); - s->endGroup(); - show(); + for(auto&i:lst) + { + QPair p=i.value>(); + setupRow(p.first,p.second); + } +} + +void *qmpDevPropDialog::save() +{ + QList ret; + for(int i=0;itwProps->rowCount();++i) + { + QPair p + { + ui->twProps->item(i,0)->text(), + ui->twProps->item(i,2)->text() + }; + ret.push_back(QVariant::fromValue(p)); + } + return new QVariant(ret); } void qmpDevPropDialog::on_pbAdd_clicked() @@ -74,7 +93,7 @@ void qmpDevPropDialog::setupRow(const QString&dn,const QString&din) ui->twProps->setItem(r,3,new QTableWidgetItem("...")); if(din.length())ui->twProps->item(r,2)->setText(din); cbx->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable); - cbx->setText("Disconnected"); + cbx->setText(tr("Disconnected")); ui->twProps->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::ResizeToContents); if(dn.length()) { @@ -89,14 +108,10 @@ void qmpDevPropDialog::setupRow(const QString&dn,const QString&din) void qmpDevPropDialog::on_buttonBox_accepted() { - QSettings *s=qmpSettingsWindow::getSettingsIntf(); - s->beginGroup("DevInit"); - s->remove(""); - for(int i=0;itwProps->rowCount();++i) - { - s->setValue(ui->twProps->item(i,0)->text(), - ui->twProps->item(i,2)->text()); - } - s->endGroup(); - s->sync(); + accept(); +} + +void qmpDevPropDialog::on_buttonBox_rejected() +{ + reject(); } diff --git a/qmidiplayer-desktop/qmpdevpropdialog.hpp b/qmidiplayer-desktop/qmpdevpropdialog.hpp index cd0d150..e98aba9 100644 --- a/qmidiplayer-desktop/qmpdevpropdialog.hpp +++ b/qmidiplayer-desktop/qmpdevpropdialog.hpp @@ -9,12 +9,13 @@ class qmpDevPropDialog; class qmpDevPropDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: explicit qmpDevPropDialog(QWidget *parent = nullptr); - void launch(); ~qmpDevPropDialog(); + void load(void* data); + void* save(); private slots: void on_pbAdd_clicked(); @@ -23,6 +24,8 @@ class qmpDevPropDialog : public QDialog void on_buttonBox_accepted(); + void on_buttonBox_rejected(); + private: Ui::qmpDevPropDialog *ui; void setupRow(const QString &dn="",const QString &din=""); diff --git a/qmidiplayer-desktop/qmpefxwindow.cpp b/qmidiplayer-desktop/qmpefxwindow.cpp index 631ccdb..f8731ba 100644 --- a/qmidiplayer-desktop/qmpefxwindow.cpp +++ b/qmidiplayer-desktop/qmpefxwindow.cpp @@ -12,19 +12,19 @@ qmpEfxWindow::qmpEfxWindow(QWidget *parent) : QList dials=findChildren(); for(int i=0;isetStyle(styl); - QSettings *settings=qmpSettingsWindow::getSettingsIntf(); - ui->cbEnabledC->setChecked(settings->value("Effects/ChorusEnabled",1).toInt()); - ui->cbEnabledR->setChecked(settings->value("Effects/ReverbEnabled",1).toInt()); - rr=settings->value("Effects/ReverbRoom",0.2).toDouble(); - rd=settings->value("Effects/ReverbDamp",0.0).toDouble(); - rw=settings->value("Effects/ReverbWidth",0.5).toDouble(); - rl=settings->value("Effects/ReverbLevel",0.9).toDouble(); - - cfb=settings->value("Effects/ChorusFeedbk",3).toInt(); - cl=settings->value("Effects/ChorusLevel",2.0).toDouble(); - cr=settings->value("Effects/ChorusRate",0.3).toDouble(); - cd=settings->value("Effects/ChorusDepth",8.0).toDouble(); - ct=settings->value("Effects/ChorusType",FLUID_CHORUS_MOD_SINE).toInt(); + qmpSettings *settings=qmpMainWindow::getInstance()->getSettings(); + ui->cbEnabledC->setChecked(settings->getOptionRaw("Effects/ChorusEnabled",1).toInt()); + ui->cbEnabledR->setChecked(settings->getOptionRaw("Effects/ReverbEnabled",1).toInt()); + rr=settings->getOptionRaw("Effects/ReverbRoom",0.2).toDouble(); + rd=settings->getOptionRaw("Effects/ReverbDamp",0.0).toDouble(); + rw=settings->getOptionRaw("Effects/ReverbWidth",0.5).toDouble(); + rl=settings->getOptionRaw("Effects/ReverbLevel",0.9).toDouble(); + + cfb=settings->getOptionRaw("Effects/ChorusFeedbk",3).toInt(); + cl=settings->getOptionRaw("Effects/ChorusLevel",2.0).toDouble(); + cr=settings->getOptionRaw("Effects/ChorusRate",0.3).toDouble(); + cd=settings->getOptionRaw("Effects/ChorusDepth",8.0).toDouble(); + ct=settings->getOptionRaw("Effects/ChorusType",FLUID_CHORUS_MOD_SINE).toInt(); qmpMainWindow::getInstance()->registerFunctionality( efxf=new qmpEfxFunc(this), std::string("Effects"), @@ -33,9 +33,9 @@ qmpEfxWindow::qmpEfxWindow(QWidget *parent) : 0, true ); - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) - setGeometry(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxW",QRect(-999,-999,999,999)).toRect()); - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxWShown",0).toInt()) + if(settings->getOptionRaw("DialogStatus/EfxW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) + setGeometry(settings->getOptionRaw("DialogStatus/EfxW",QRect(-999,-999,999,999)).toRect()); + if(settings->getOptionRaw("DialogStatus/EfxWShown",0).toInt()) {show();qmpMainWindow::getInstance()->setFuncState("Effects",true);} } @@ -49,14 +49,15 @@ qmpEfxWindow::~qmpEfxWindow() void qmpEfxWindow::closeEvent(QCloseEvent *event) { - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + qmpSettings *settings=qmpMainWindow::getInstance()->getSettings(); + if(settings->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxW",geometry()); + settings->setOptionRaw("DialogStatus/EfxW",geometry()); } setVisible(false); - if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + if(!qmpMainWindow::getInstance()->isFinalizing()&&settings->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxWShown",0); + settings->setOptionRaw("DialogStatus/EfxWShown",0); } qmpMainWindow::getInstance()->setFuncState("Effects",false); event->accept(); @@ -83,11 +84,12 @@ void qmpEfxWindow::showEvent(QShowEvent *event) if(ct==FLUID_CHORUS_MOD_SINE)ui->rbSine->setChecked(true),ui->rbTriangle->setChecked(false); if(ct==FLUID_CHORUS_MOD_TRIANGLE)ui->rbSine->setChecked(false),ui->rbTriangle->setChecked(true); initialized=true; - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) - setGeometry(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/EfxW",QRect(-999,-999,999,999)).toRect()); - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + qmpSettings *settings=qmpMainWindow::getInstance()->getSettings(); + if(settings->getOptionRaw("DialogStatus/EfxW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) + setGeometry(settings->getOptionRaw("DialogStatus/EfxW",QRect(-999,-999,999,999)).toRect()); + if(settings->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/EfxWShown",1); + settings->setOptionRaw("DialogStatus/EfxWShown",1); } event->accept(); } @@ -105,19 +107,19 @@ void qmpEfxWindow::sendEfxChange(void *_fs) fs->setReverbPara(ui->cbEnabledR->isChecked()?1:0,rr,rd,rw,rl); fs->setChorusPara(ui->cbEnabledC->isChecked()?1:0,cfb,cl,cr,cd,ct); - QSettings *settings=qmpSettingsWindow::getSettingsIntf(); - settings->setValue("Effects/ChorusEnabled",ui->cbEnabledC->isChecked()?1:0); - settings->setValue("Effects/ReverbEnabled",ui->cbEnabledR->isChecked()?1:0); - settings->setValue("Effects/ReverbRoom",rr); - settings->setValue("Effects/ReverbDamp",rd); - settings->setValue("Effects/ReverbWidth",rw); - settings->setValue("Effects/ReverbLevel",rl); - - settings->setValue("Effects/ChorusFeedbk",cfb); - settings->setValue("Effects/ChorusLevel",cl); - settings->setValue("Effects/ChorusRate",cr); - settings->setValue("Effects/ChorusDepth",cd); - settings->setValue("Effects/ChorusType",ct); + qmpSettings *settings=qmpMainWindow::getInstance()->getSettings(); + settings->setOptionRaw("Effects/ChorusEnabled",ui->cbEnabledC->isChecked()?1:0); + settings->setOptionRaw("Effects/ReverbEnabled",ui->cbEnabledR->isChecked()?1:0); + settings->setOptionRaw("Effects/ReverbRoom",rr); + settings->setOptionRaw("Effects/ReverbDamp",rd); + settings->setOptionRaw("Effects/ReverbWidth",rw); + settings->setOptionRaw("Effects/ReverbLevel",rl); + + settings->setOptionRaw("Effects/ChorusFeedbk",cfb); + settings->setOptionRaw("Effects/ChorusLevel",cl); + settings->setOptionRaw("Effects/ChorusRate",cr); + settings->setOptionRaw("Effects/ChorusDepth",cd); + settings->setOptionRaw("Effects/ChorusType",ct); } void qmpEfxWindow::dailValueChange() diff --git a/qmidiplayer-desktop/qmpinfowindow.cpp b/qmidiplayer-desktop/qmpinfowindow.cpp index d1485be..c0b8892 100644 --- a/qmidiplayer-desktop/qmpinfowindow.cpp +++ b/qmidiplayer-desktop/qmpinfowindow.cpp @@ -47,22 +47,22 @@ void qmpInfoWindow::updateInfo() { char str[256]; CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); - QSettings* settings=qmpSettingsWindow::getSettingsIntf(); + std::string textencoding=qmpMainWindow::getInstance()->getSettings()->getOptionEnumIntOptName("Midi/TextEncoding"); ui->lbFileName->setText(QString("File name: ")+qmpMainWindow::getInstance()->getFileName()); if(player->getTitle()) { - if(settings->value("Midi/TextEncoding","").toString()!="Unicode") + if(textencoding!="Unicode") ui->lbTitle->setText(QString("Title: ")+ - QTextCodec::codecForName(settings->value("Midi/TextEncoding","").toString().toStdString().c_str())->toUnicode(player->getTitle())); + QTextCodec::codecForName(textencoding.c_str())->toUnicode(player->getTitle())); else ui->lbTitle->setText(QString("Title: ")+player->getTitle()); } else ui->lbTitle->setText(QString("Title: ")); if(player->getCopyright()) { - if(settings->value("Midi/TextEncoding","").toString()!="Unicode") + if(textencoding!="Unicode") ui->lbCopyright->setText(QString("Copyright: ")+ - QTextCodec::codecForName(settings->value("Midi/TextEncoding","").toString().toStdString().c_str())->toUnicode(player->getCopyright())); + QTextCodec::codecForName(textencoding.c_str())->toUnicode(player->getCopyright())); else ui->lbCopyright->setText(QString("Copyright: ")+player->getCopyright()); } diff --git a/qmidiplayer-desktop/qmpmainwindow.cpp b/qmidiplayer-desktop/qmpmainwindow.cpp index 94185c7..d2a0e6b 100644 --- a/qmidiplayer-desktop/qmpmainwindow.cpp +++ b/qmidiplayer-desktop/qmpmainwindow.cpp @@ -39,7 +39,8 @@ qmpMainWindow::qmpMainWindow(QCommandLineParser *_clp,QWidget *parent): setButtonHeight(ui->pbNext,36);setButtonHeight(ui->pbPlayPause,36);setButtonHeight(ui->pbAdd,36); setButtonHeight(ui->pbPrev,36);setButtonHeight(ui->pbSettings,36);setButtonHeight(ui->pbStop,36); playing=false;stopped=true;dragging=false;fin=false; - settingsw=new qmpSettingsWindow(this); + settings.reset(new qmpSettings()); + settingsw=new qmpSettingsWindow(settings.get(),this); player=nullptr;timer=nullptr;fluidrenderer=nullptr; } @@ -71,32 +72,33 @@ qmpMainWindow::~qmpMainWindow() void qmpMainWindow::init() { - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus",0).toInt()) - { - QRect g=qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/MainW",QRect(-999,-999,999,999)).toRect(); - if(g!=QRect(-999,-999,999,999))setGeometry(g); - }show(); - + show(); ui->centralWidget->setEnabled(false); + + pmgr=new qmpPluginManager(); + registerMidiOptions(); + std::future f=std::async(std::launch::async, [this] { player=new CMidiPlayer(); + reloadsynf=new qmpReloadSynthFunc(this); + player->registerFluidOptions(pmgr->pluginAPI); + playerSetup(player->fluid()); + player->fluid()->deviceInit(); + loadSoundFont(player->fluid()); auto rtdev=qmpRtMidiManager::getDevices(); for(auto &i:rtdev) - { player->registerMidiOutDevice(i.first,i.second); - QString di=qmpSettingsWindow::getSettingsIntf()->value(QString("DevInit/%1").arg(QString::fromStdString(i.second)),"").toString(); - if(di.length())i.first->setInitializerFile(di.toUtf8().data()); - } - reloadsynf=new qmpReloadSynthFunc(this); - playerSetup(player->fluid());player->fluid()->deviceInit(); - loadSoundFont(player->fluid()); } ); while(f.wait_for(std::chrono::milliseconds(100))==std::future_status::timeout); ui->centralWidget->setEnabled(true); + settingsw->registerSoundFontOption(); + registerBehaviorOptions(); + settingsw->registerCustomizeWidgetOptions(); + plistw=new qmpPlistWindow(this); chnlw=new qmpChannelsWindow(this); efxw=new qmpEfxWindow(this); @@ -110,17 +112,45 @@ void qmpMainWindow::init() plistw->emptyList(); for(auto&i:argfiles)plistw->insertItem(i); } + + if(settings->getOptionBool("Behavior/DialogStatus")) + { + QRect g=settings->getOptionRaw("DialogStatus/MainW",QRect(-999,-999,999,999)).toRect(); + if(g!=QRect(-999,-999,999,999))setGeometry(g); + } + registerFunctionality(renderf,"Render",tr("Render to wave").toStdString(),getThemedIconc(":/img/render.svg"),0,false); registerFunctionality(panicf,"Panic",tr("Panic").toStdString(),getThemedIconc(":/img/panic.svg"),0,false); registerFunctionality(reloadsynf,"ReloadSynth",tr("Restart fluidsynth").toStdString(),getThemedIconc(":/img/repeat-base.svg"),0,false); - pmgr=new qmpPluginManager(); const QStringList &qpp=clp->values("plugin"); std::vector pp; for(auto s:qpp) pp.push_back(s.toStdString()); pmgr->scanPlugins(pp); - settingsw->updatePluginList(pmgr);pmgr->initPlugins(); - ui->vsMasterVol->setValue(qmpSettingsWindow::getSettingsIntf()->value("Audio/Gain",50).toInt()); + settingsw->registerPluginOption(pmgr); + settingsw->updatePluginList(pmgr); + pmgr->initPlugins(); + + settingsw->registerExtraMidiOptions(); + + QVariant* dinif_v=static_cast(settings->getOptionCustom("Midi/DeviceInitializationFiles")); + QList devinif_list=dinif_v->toList(); + delete dinif_v; + QMap devinif_map; + for(auto &i:devinif_list) + { + QPair p=i.value>(); + devinif_map[p.first]=p.second; + } + auto rtdev=qmpRtMidiManager::getDevices(); + for(auto &i:rtdev) + { + if(devinif_map.contains(QString(i.second.c_str()))) + i.first->setInitializerFile(devinif_map[QString(i.second.c_str())].toStdString().c_str()); + } + chnlw->selectDefaultDevice(); + + ui->vsMasterVol->setValue(settings->getOptionRaw("Audio/Gain",50).toInt()); connect(timer,&QTimer::timeout,this,&qmpMainWindow::updateWidgets); connect(timer,&QTimer::timeout,infow,&qmpInfoWindow::updateInfo); ui->pbNext->setIcon(QIcon(getThemedIcon(":/img/next.svg"))); @@ -141,7 +171,7 @@ int qmpMainWindow::parseArgs() { if(QFileInfo(args.at(i)).exists()) { - if(loadfolder||qmpSettingsWindow::getSettingsIntf()->value("Behavior/LoadFolder",0).toInt()) + if(loadfolder||settings->getOptionBool("Behavior/LoadFolder")) { QDirIterator di(QFileInfo(args.at(i)).absolutePath()); while(di.hasNext()) @@ -159,9 +189,9 @@ int qmpMainWindow::parseArgs() void qmpMainWindow::closeEvent(QCloseEvent *event) { - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + if(settings->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/MainW",geometry()); + settings->setOptionRaw("DialogStatus/MainW",geometry()); } on_pbStop_clicked();fin=true; for(auto i=mfunc.begin();i!=mfunc.end();++i) @@ -261,7 +291,7 @@ void qmpMainWindow::switchTrack(QString s) player->playerInit(); invokeCallback("main.start",nullptr); player->fluid()->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); - player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); + player->setWaitVoice(settings->getOptionBool("Midi/WaitVoice")); playerTh=new std::thread(&CMidiPlayer::playerThread,player); #ifdef _WIN32 SetThreadPriority((void*)playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); @@ -271,61 +301,51 @@ void qmpMainWindow::switchTrack(QString s) } std::string qmpMainWindow::getTitle() { - if(!qmpSettingsWindow::getSettingsIntf())return ""; - if(qmpSettingsWindow::getSettingsIntf()->value("Midi/TextEncoding","").toString() - =="Unicode")return std::string(player->getTitle()); + if(settings->getOptionEnumIntOptName("Midi/TextEncoding")=="Unicode") + return std::string(player->getTitle()); return QTextCodec::codecForName( - qmpSettingsWindow::getSettingsIntf()->value("Midi/TextEncoding",""). - toString().toStdString().c_str())-> + settings->getOptionEnumIntOptName("Midi/TextEncoding").c_str())-> toUnicode(player->getTitle()).toStdString(); } std::wstring qmpMainWindow::getWTitle() { - if(!qmpSettingsWindow::getSettingsIntf())return L""; - if(qmpSettingsWindow::getSettingsIntf()->value("Midi/TextEncoding","").toString() - =="Unicode")return QString(player->getTitle()).toStdWString(); + if(settings->getOptionEnumIntOptName("Midi/TextEncoding")=="Unicode") + return QString(player->getTitle()).toStdWString(); return QTextCodec::codecForName( - qmpSettingsWindow::getSettingsIntf()->value("Midi/TextEncoding",""). - toString().toStdString().c_str())-> + settings->getOptionEnumIntOptName("Midi/TextEncoding").c_str())-> toUnicode(player->getTitle()).toStdWString(); } void qmpMainWindow::playerSetup(IFluidSettings* fs) { - QSettings* settings=qmpSettingsWindow::getSettingsIntf(); - fs->setOptStr("audio.driver",settings->value("Audio/Driver","").toString().toStdString().c_str()); - fs->setOptInt("audio.period-size",settings->value("Audio/BufSize","").toInt()); - fs->setOptInt("audio.periods",settings->value("Audio/BufCnt","").toInt()); - fs->setOptStr("audio.sample-format",settings->value("Audio/Format","").toString().toStdString().c_str()); - fs->setOptNum("synth.sample-rate",settings->value("Audio/Frequency","").toInt()); - fs->setOptInt("synth.polyphony",settings->value("Audio/Polyphony","").toInt()); - fs->setOptInt("synth.cpu-cores",settings->value("Audio/Threads","").toInt()); - char bsmode[4]; - if(settings->value("Audio/AutoBS",1).toInt()&&player->getFileStandard()) + fs->setOptStr("audio.driver",settings->getOptionEnumIntOptName("FluidSynth/AudioDriver").c_str()); + fs->setOptInt("audio.period-size",settings->getOptionInt("FluidSynth/BufSize")); + fs->setOptInt("audio.periods",settings->getOptionInt("FluidSynth/BufCnt")); + fs->setOptStr("audio.sample-format",settings->getOptionEnumIntOptName("FluidSynth/SampleFormat").c_str()); + fs->setOptNum("synth.sample-rate",settings->getOptionInt("FluidSynth/SampleRate")); + fs->setOptInt("synth.polyphony",settings->getOptionInt("FluidSynth/Polyphony")); + fs->setOptInt("synth.cpu-cores",settings->getOptionInt("FluidSynth/Threads")); + std::string bsmode; + if(settings->getOptionBool("FluidSynth/AutoBS")&&player->getFileStandard()) switch(player->getFileStandard()) { - case 1:strcpy(bsmode,"gm");break; - case 2:strcpy(bsmode,"mma");break; - case 3:strcpy(bsmode,"gs");break; - case 4:strcpy(bsmode,"xg");break; + case 1:bsmode="gm";break; + case 2:bsmode="mma";break; + case 3:bsmode="gs";break; + case 4:bsmode="xg";break; } else { - if(settings->value("Audio/BankSelect","CC#0").toString()==QString("Ignored")) - strcpy(bsmode,"gm"); - if(settings->value("Audio/BankSelect","CC#0").toString()==QString("CC#0")) - strcpy(bsmode,"gs"); - if(settings->value("Audio/BankSelect","CC#0").toString()==QString("CC#32")) - strcpy(bsmode,"xg"); - if(settings->value("Audio/BankSelect","CC#0").toString()==QString("CC#0*128+CC#32")) - strcpy(bsmode,"mma"); + bsmode=settings->getOptionEnumIntOptName("FluidSynth/BankSelect"); + std::transform(bsmode.begin(),bsmode.end(),bsmode.begin(),[](char i){return tolower(i);}); } - fs->setOptStr("synth.midi-bank-select",bsmode); - player->sendSysX(settings->value("Midi/SendSysEx",1).toInt()); + fs->setOptStr("synth.midi-bank-select",bsmode.c_str()); + player->sendSysX(settings->getOptionBool("Midi/SendSysEx")); } void qmpMainWindow::loadSoundFont(IFluidSettings *fs) { - QList sflist=settingsw->getSettingsIntf()->value("Audio/SoundFonts",QList{}).toList(); + QVariant *data=static_cast(settings->getOptionCustom("FluidSynth/SoundFonts")); + QList sflist=data->toList(); for(auto i=sflist.rbegin();i!=sflist.rend();++i) { if(i->toString().startsWith('#'))continue; @@ -338,6 +358,7 @@ void qmpMainWindow::loadSoundFont(IFluidSettings *fs) fs->loadSFont(sf.toStdString().c_str()); #endif } + delete data; } int qmpMainWindow::loadFile(QString fns) { @@ -357,6 +378,23 @@ int qmpMainWindow::loadFile(QString fns) return ret; } +void qmpMainWindow::registerMidiOptions() +{ + settings->registerOptionBool("MIDI","Disable MIDI Mapping","Midi/DisableMapping",false); + settings->registerOptionBool("MIDI","Send system exclusive messages","Midi/SendSysEx",true); + settings->registerOptionBool("MIDI","Wait for remaining voice before stopping","Midi/WaitVoice",true); + settings->registerOptionEnumInt("MIDI","Text encoding","Midi/TextEncoding",{"Unicode","Big5","Big5-HKSCS","CP949","EUC-JP","EUC-KR","GB18030","KOI8-R","KOI8-U","Macintosh","Shift-JIS"},0); +} + +void qmpMainWindow::registerBehaviorOptions() +{ + settings->registerOptionBool("Behavior","Restore last playlist on startup","Behavior/RestorePlaylist",false); + settings->registerOptionBool("Behavior","Add files in the same folder to playlist","Behavior/LoadFolder",false); + settings->registerOptionBool("Behavior","Save dialog status","Behavior/DialogStatus",false); + settings->registerOptionBool("Behavior","Show labels beside icon in toolbar buttons","Behavior/ShowButtonLabel",false); + settings->registerOptionEnumInt("Behavior","Icon Theme","Behavior/IconTheme",{"Auto","Dark","Light"},0); +} + void qmpMainWindow::on_pbPlayPause_clicked() { playing=!playing; @@ -378,7 +416,7 @@ void qmpMainWindow::on_pbPlayPause_clicked() player->playerInit(); invokeCallback("main.start",nullptr); player->fluid()->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); - player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); + player->setWaitVoice(settings->getOptionBool("Midi/WaitVoice")); playerTh=new std::thread(&CMidiPlayer::playerThread,player); #ifdef _WIN32 SetThreadPriority((void*)playerTh->native_handle(),THREAD_PRIORITY_TIME_CRITICAL); @@ -461,7 +499,7 @@ void qmpMainWindow::playerSeek(uint32_t percentage) void qmpMainWindow::on_vsMasterVol_valueChanged() { if(!stopped)player->fluid()->setGain(ui->vsMasterVol->value()/250.); - qmpSettingsWindow::getSettingsIntf()->setValue("Audio/Gain",ui->vsMasterVol->value()); + settings->setOptionRaw("Audio/Gain",ui->vsMasterVol->value()); } void qmpMainWindow::on_pbStop_clicked() @@ -567,11 +605,11 @@ void qmpMainWindow::setFuncEnabled(std::string name,bool enable) bool qmpMainWindow::isDarkTheme() { - if(!qmpSettingsWindow::getSettingsIntf()->value("Behavior/IconTheme",0).toInt()) + if(!settings->getOptionEnumInt("Behavior/IconTheme")) { return ui->centralWidget->palette().color(QPalette::Background).lightness()<128; } - else return 2-qmpSettingsWindow::getSettingsIntf()->value("Behavior/IconTheme",0).toInt(); + else return 2-settings->getOptionEnumInt("Behavior/IconTheme"); } void qmpMainWindow::startRender() @@ -614,16 +652,26 @@ void qmpMainWindow::reloadSynth() ui->centralWidget->setEnabled(true); } -std::vector& qmpMainWindow::getWidgets(int w) -{return w?enabled_actions:enabled_buttons;} std::map& qmpMainWindow::getFunc() {return mfunc;} void qmpMainWindow::setupWidget() { for(auto i=mfunc.begin();i!=mfunc.end();++i) - i->second.setAssignedControl((QReflectiveAction*)nullptr), - i->second.setAssignedControl((QReflectivePushButton*)nullptr); + { + i->second.setAssignedControl(static_cast(nullptr)); + i->second.setAssignedControl(static_cast(nullptr)); + } + QVariant *v=static_cast(settings->getOptionCustom("Behavior/Toolbar")); + enabled_buttons.clear(); + for(auto i:v->toList()) + enabled_buttons.push_back(i.toString().toStdString()); + delete v; + v=static_cast(settings->getOptionCustom("Behavior/Actions")); + enabled_actions.clear(); + for(auto i:v->toList()) + enabled_actions.push_back(i.toString().toStdString()); + delete v; QListw=ui->buttonwidget->findChildren("",Qt::FindDirectChildrenOnly); qDeleteAll(w); QLista=ui->lbFileName->actions(); @@ -641,7 +689,8 @@ void qmpMainWindow::setupWidget() enabled_buttons[i] ); setButtonHeight(pb,32); - if(getSettingsWindow()->getSettingsIntf()->value("Behavior/ShowButtonLabel",0).toInt()) + //!!TODO + if(settings->getOptionBool("Behavior/ShowButtonLabel")) { pb->setText(tr(mfunc[enabled_buttons[i]].desc().c_str())); pb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); diff --git a/qmidiplayer-desktop/qmpmainwindow.hpp b/qmidiplayer-desktop/qmpmainwindow.hpp index c8f3827..700b501 100644 --- a/qmidiplayer-desktop/qmpmainwindow.hpp +++ b/qmidiplayer-desktop/qmpmainwindow.hpp @@ -141,7 +141,7 @@ class qmpMainWindow:public QMainWindow void dragEnterEvent(QDragEnterEvent *event); ~qmpMainWindow(); CMidiPlayer* getPlayer(){return player;} - qmpSettingsWindow* getSettingsWindow(){return settingsw;} + qmpSettings* getSettings(){return settings.get();} QTimer* getTimer(){return timer;} bool isFinalizing(){return fin;} QString getFileName(); @@ -163,7 +163,6 @@ class qmpMainWindow:public QMainWindow void reloadSynth(); void setupWidget(); void invokeCallback(std::string cat,void *callerdat); - std::vector& getWidgets(int w); std::map& getFunc(); private slots: @@ -200,8 +199,9 @@ class qmpMainWindow:public QMainWindow QPointer chnlw; QPointer efxw; QPointer infow; - QPointer settingsw; QPointer helpw; + std::unique_ptr settings; + QPointer settingsw; std::map mfunc; std::unordered_map>> muicb; qmpRenderFunc* renderf; @@ -215,6 +215,8 @@ class qmpMainWindow:public QMainWindow void playerSetup(IFluidSettings *fs); void loadSoundFont(IFluidSettings *fs); int loadFile(QString fns); + void registerMidiOptions(); + void registerBehaviorOptions(); private: static qmpMainWindow* ref; diff --git a/qmidiplayer-desktop/qmpplistwindow.cpp b/qmidiplayer-desktop/qmpplistwindow.cpp index b4b0c02..5b46fb6 100644 --- a/qmidiplayer-desktop/qmpplistwindow.cpp +++ b/qmidiplayer-desktop/qmpplistwindow.cpp @@ -12,7 +12,7 @@ #include "qmpmainwindow.hpp" #define setButtonHeight(x,h) {x->setMaximumHeight(h*(logicalDpiY()/96.));x->setMinimumHeight(h*(logicalDpiY()/96.));} -qmpPlistWindow::qmpPlistWindow(QWidget *parent) : +qmpPlistWindow::qmpPlistWindow(QWidget *parent): QWidget(parent,Qt::Dialog), ui(new Ui::qmpPlistWindow) { @@ -23,12 +23,13 @@ qmpPlistWindow::qmpPlistWindow(QWidget *parent) : setButtonHeight(ui->pbSave,36);setButtonHeight(ui->pbShuffle,36); connect(this,&qmpPlistWindow::selectionChanging,(qmpMainWindow*)parent,&qmpMainWindow::selectionChanged); repeat=0;shuffle=0; - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/RestorePlaylist","").toInt()) + settings=qmpMainWindow::getInstance()->getSettings(); + if(settings->getOptionBool("Behavior/RestorePlaylist")) { QSettings* plist=new QSettings(QStandardPaths::writableLocation(QStandardPaths::StandardLocation::ConfigLocation)+QString("/qmpplist"), QSettings::IniFormat); int fc=plist->value("Playlist/FileCount",0).toInt(); - ui->lwFiles->clear();for(int i=1;i<=fc;++i) + ui->lwFiles->clear();for(int i=0;ilwFiles->addItem(plist->value("Playlist/File"+QString("%1").arg(i,5,10,QChar('0')),"").toString()); repeat=plist->value("Playlist/Repeat",0).toInt(); shuffle=plist->value("Playlist/Shuffle",0).toInt(); @@ -75,9 +76,9 @@ qmpPlistWindow::qmpPlistWindow(QWidget *parent) : 0, true ); - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) - setGeometry(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListW",QRect(-999,-999,999,999)).toRect()); - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListWShown",0).toInt()) + if(settings->getOptionRaw("DialogStatus/PListW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) + setGeometry(settings->getOptionRaw("DialogStatus/PListW",QRect(-999,-999,999,999)).toRect()); + if(settings->getOptionRaw("DialogStatus/PListWShown",0).toInt()) {show();qmpMainWindow::getInstance()->setFuncState("Playlist",true);} } @@ -90,35 +91,35 @@ qmpPlistWindow::~qmpPlistWindow() void qmpPlistWindow::showEvent(QShowEvent *event) { - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + if(settings->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListWShown",1); + settings->setOptionRaw("DialogStatus/PListWShown",1); } - if(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) - setGeometry(qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/PListW",QRect(-999,-999,999,999)).toRect()); + if(settings->getOptionRaw("DialogStatus/PListW",QRect(-999,-999,999,999)).toRect()!=QRect(-999,-999,999,999)) + setGeometry(settings->getOptionRaw("DialogStatus/PListW",QRect(-999,-999,999,999)).toRect()); event->accept(); } void qmpPlistWindow::closeEvent(QCloseEvent *event) { - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + if(settings->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListW",geometry()); + settings->setOptionRaw("DialogStatus/PListW",geometry()); } setVisible(false); if(!qmpMainWindow::getInstance()->isFinalizing()) while(ui->lwFiles->count()>1)delete ui->lwFiles->item(0); - if(!qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) + if(!qmpMainWindow::getInstance()->isFinalizing()&&settings->getOptionBool("Behavior/DialogStatus")) { - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/PListWShown",0); + settings->setOptionRaw("DialogStatus/PListWShown",0); } - if(qmpMainWindow::getInstance()->isFinalizing()&&qmpSettingsWindow::getSettingsIntf()->value("Behavior/RestorePlaylist","").toInt()) + if(qmpMainWindow::getInstance()->isFinalizing()&&settings->getOptionBool("Behavior/RestorePlaylist")) { QSettings* plist=new QSettings(QStandardPaths::writableLocation(QStandardPaths::StandardLocation::ConfigLocation)+QString("/qmpplist"), QSettings::IniFormat); plist->setValue("Playlist/FileCount",ui->lwFiles->count()); for(int i=0;ilwFiles->count();++i) - plist->setValue("Playlist/File"+QString("%1").arg(i+1,5,10,QChar('0')),ui->lwFiles->item(i)->text()); + plist->setValue("Playlist/File"+QString("%1").arg(i,5,10,QChar('0')),ui->lwFiles->item(i)->text()); plist->setValue("Playlist/Repeat",repeat); plist->setValue("Playlist/Shuffle",shuffle); plist->sync(); @@ -158,16 +159,16 @@ void qmpPlistWindow::insertItems(QStringList il) int qmpPlistWindow::on_pbAdd_clicked() { QStringList sl; - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - sl=QFileDialog::getOpenFileNames(this,"Add File",qmpSettingsWindow::getSettingsIntf()->value("DialogStatus/FileDialogPath","").toString(),"Midi files (*.mid *.midi)"); + if(settings->getOptionBool("Behavior/DialogStatus")) + sl=QFileDialog::getOpenFileNames(this,"Add File",settings->getOptionRaw("DialogStatus/FileDialogPath","").toString(),"Midi files (*.mid *.midi)"); else sl=QFileDialog::getOpenFileNames(this,"Add File","","Midi files (*.mid *.midi *.rmi)"); if(sl.empty())return 0; for(int i=0;ilwFiles->addItem(new QListWidgetItem(sl.at(i))); if(!isVisible())while(ui->lwFiles->count()>1)delete ui->lwFiles->item(0); - if(qmpSettingsWindow::getSettingsIntf()->value("Behavior/DialogStatus","").toInt()) - qmpSettingsWindow::getSettingsIntf()->setValue("DialogStatus/FileDialogPath", + if(settings->getOptionBool("Behavior/DialogStatus")) + settings->setOptionRaw("DialogStatus/FileDialogPath", QUrl(sl.at(0)).toString(QUrl::RemoveFilename)); return 1; } @@ -293,7 +294,7 @@ void qmpPlistWindow::on_pbSave_clicked() QSettings::IniFormat); plist->setValue("Playlist/FileCount",ui->lwFiles->count()); for(int i=0;ilwFiles->count();++i) - plist->setValue("Playlist/File"+QString("%1").arg(i+1,5,10,QChar('0')),ui->lwFiles->item(i)->text()); + plist->setValue("Playlist/File"+QString("%1").arg(i,5,10,QChar('0')),ui->lwFiles->item(i)->text()); plist->setValue("Playlist/Repeat",repeat); plist->setValue("Playlist/Shuffle",shuffle); plist->sync(); @@ -306,7 +307,7 @@ void qmpPlistWindow::on_pbLoad_clicked() QSettings::IniFormat); int fc=plist->value("Playlist/FileCount",0).toInt(); if(!fc){delete plist;return;} - ui->lwFiles->clear();for(int i=1;i<=fc;++i) + ui->lwFiles->clear();for(int i=0;ilwFiles->addItem(plist->value("Playlist/File"+QString("%1").arg(i,5,10,QChar('0')),"").toString()); repeat=plist->value("Playlist/Repeat",0).toInt(); shuffle=plist->value("Playlist/Shuffle",0).toInt(); diff --git a/qmidiplayer-desktop/qmpplistwindow.hpp b/qmidiplayer-desktop/qmpplistwindow.hpp index 4fe0b50..afd3ae3 100644 --- a/qmidiplayer-desktop/qmpplistwindow.hpp +++ b/qmidiplayer-desktop/qmpplistwindow.hpp @@ -15,6 +15,7 @@ namespace Ui { } class qmpPlistWindow; +class qmpSettings; class qmpPlistFunc:public qmpFuncBaseIntf { @@ -65,6 +66,7 @@ class qmpPlistWindow:public QWidget qmpPlistFunc* plistf; Ui::qmpPlistWindow *ui; int shuffle,repeat;//rep 0=off 1=one 2=all + qmpSettings* settings; }; #endif // QMPPLISTWINDOW_H diff --git a/qmidiplayer-desktop/qmpplugin.cpp b/qmidiplayer-desktop/qmpplugin.cpp index 08959cb..8a156ba 100644 --- a/qmidiplayer-desktop/qmpplugin.cpp +++ b/qmidiplayer-desktop/qmpplugin.cpp @@ -9,9 +9,8 @@ #include "qmpplugin.hpp" #include "qmpmainwindow.hpp" #include "qmpsettingswindow.hpp" -qmpPluginAPI* pluginAPI; -qmpMainWindow* qmw; -qmpSettingsWindow* qsw; +qmpPluginAPI* qmpPluginManager::pluginAPI=nullptr; +qmpMainWindow* qmpPluginManager::mainwindow=nullptr; #ifdef _WIN32 #include #include @@ -93,8 +92,7 @@ void qmpPluginManager::scanPlugins(const std::vector &pp) #endif qmpPluginManager::qmpPluginManager() { - qmw=qmpMainWindow::getInstance(); - qsw=qmw->getSettingsWindow(); + mainwindow=qmpMainWindow::getInstance(); pluginAPI=new qmpPluginAPI(); } qmpPluginManager::~qmpPluginManager() @@ -104,7 +102,7 @@ qmpPluginManager::~qmpPluginManager() if(plugins[i].initialized)plugins[i].pinterface->deinit(); delete plugins[i].pinterface; } - qmw=nullptr;qsw=nullptr;delete pluginAPI; + mainwindow=nullptr;delete pluginAPI; } std::vector *qmpPluginManager::getPlugins() { @@ -130,6 +128,7 @@ void qmpPluginManager::deinitPlugins() qmpPluginAPI::~qmpPluginAPI(){} +#define qmw qmpPluginManager::mainwindow uint32_t qmpPluginAPI::getDivision() {return qmw&&qmw->getPlayer()?qmw->getPlayer()->getDivision():0;} uint32_t qmpPluginAPI::getRawTempo() @@ -244,26 +243,26 @@ void qmpPluginAPI::unregisterFileReadFinishHook(int id) {qmw->getPlayer()->unregisterFileReadFinishHook(id);} void qmpPluginAPI::registerOptionInt(std::string tab,std::string desc,std::string key,int min,int max,int defaultval) -{qsw->registerOptionInt(tab,desc,key,min,max,defaultval);} -int qmpPluginAPI::getOptionInt(std::string key){return qsw->getOptionInt(key);} -void qmpPluginAPI::setOptionInt(std::string key,int val){qsw->setOptionInt(key,val);} +{qmw->getSettings()->registerOptionInt(tab,desc,key,min,max,defaultval);} +int qmpPluginAPI::getOptionInt(std::string key){return qmw->getSettings()->getOptionInt(key);} +void qmpPluginAPI::setOptionInt(std::string key,int val){qmw->getSettings()->setOptionInt(key,val);} void qmpPluginAPI::registerOptionUint(std::string tab,std::string desc,std::string key,unsigned min,unsigned max,unsigned defaultval) -{qsw->registerOptionUint(tab,desc,key,min,max,defaultval);} -unsigned qmpPluginAPI::getOptionUint(std::string key){return qsw->getOptionUint(key);} -void qmpPluginAPI::setOptionUint(std::string key,unsigned val){qsw->setOptionUint(key,val);} +{qmw->getSettings()->registerOptionUint(tab,desc,key,min,max,defaultval);} +unsigned qmpPluginAPI::getOptionUint(std::string key){return qmw->getSettings()->getOptionUint(key);} +void qmpPluginAPI::setOptionUint(std::string key,unsigned val){qmw->getSettings()->setOptionUint(key,val);} void qmpPluginAPI::registerOptionBool(std::string tab,std::string desc,std::string key,bool defaultval) -{qsw->registerOptionBool(tab,desc,key,defaultval);} -bool qmpPluginAPI::getOptionBool(std::string key){return qsw->getOptionBool(key);} -void qmpPluginAPI::setOptionBool(std::string key,bool val){qsw->setOptionBool(key,val);} +{qmw->getSettings()->registerOptionBool(tab,desc,key,defaultval);} +bool qmpPluginAPI::getOptionBool(std::string key){return qmw->getSettings()->getOptionBool(key);} +void qmpPluginAPI::setOptionBool(std::string key,bool val){qmw->getSettings()->setOptionBool(key,val);} void qmpPluginAPI::registerOptionDouble(std::string tab,std::string desc,std::string key,double min,double max,double defaultval) -{qsw->registerOptionDouble(tab,desc,key,min,max,defaultval);} -double qmpPluginAPI::getOptionDouble(std::string key){return qsw->getOptionDouble(key);} -void qmpPluginAPI::setOptionDouble(std::string key,double val){qsw->setOptionDouble(key,val);} +{qmw->getSettings()->registerOptionDouble(tab,desc,key,min,max,defaultval);} +double qmpPluginAPI::getOptionDouble(std::string key){return qmw->getSettings()->getOptionDouble(key);} +void qmpPluginAPI::setOptionDouble(std::string key,double val){qmw->getSettings()->setOptionDouble(key,val);} void qmpPluginAPI::registerOptionString(std::string tab,std::string desc,std::string key,std::string defaultval,bool ispath) -{qsw->registerOptionString(tab,desc,key,defaultval,ispath);} -std::string qmpPluginAPI::getOptionString(std::string key){return qsw->getOptionString(key);} -void qmpPluginAPI::setOptionString(std::string key,std::string val){return qsw->setOptionString(key,val);} +{qmw->getSettings()->registerOptionString(tab,desc,key,defaultval,ispath);} +std::string qmpPluginAPI::getOptionString(std::string key){return qmw->getSettings()->getOptionString(key);} +void qmpPluginAPI::setOptionString(std::string key,std::string val){return qmw->getSettings()->setOptionString(key,val);} void qmpPluginAPI::registerOptionEnumInt(std::string tab,std::string desc,std::string key,std::vector options,int defaultval) -{qsw->registerOptionEnumInt(tab,desc,key,options,defaultval);} -int qmpPluginAPI::getOptionEnumInt(std::string key){return qsw->getOptionEnumInt(key);} -void qmpPluginAPI::setOptionEnumInt(std::string key,int val){return qsw->setOptionEnumInt(key,val);} +{qmw->getSettings()->registerOptionEnumInt(tab,desc,key,options,defaultval);} +int qmpPluginAPI::getOptionEnumInt(std::string key){return qmw->getSettings()->getOptionEnumInt(key);} +void qmpPluginAPI::setOptionEnumInt(std::string key,int val){return qmw->getSettings()->setOptionEnumInt(key,val);} diff --git a/qmidiplayer-desktop/qmpplugin.hpp b/qmidiplayer-desktop/qmpplugin.hpp index be10b12..0020530 100644 --- a/qmidiplayer-desktop/qmpplugin.hpp +++ b/qmidiplayer-desktop/qmpplugin.hpp @@ -13,10 +13,15 @@ struct qmpPlugin qmpPlugin(std::string _n,std::string _v,std::string _p,qmpPluginIntf* _i) {name=_n;version=_v;path=_p;pinterface=_i;enabled=initialized=false;} }; +class qmpMainWindow; +class qmpSettings; class qmpPluginManager { private: std::vector plugins; + static qmpPluginAPI* pluginAPI; + static qmpMainWindow* mainwindow; + static qmpSettings* settings; public: qmpPluginManager(); ~qmpPluginManager(); @@ -24,5 +29,7 @@ class qmpPluginManager void scanPlugins(const std::vector &pp); void initPlugins(); void deinitPlugins(); + friend class qmpPluginAPI; + friend class qmpMainWindow; }; #endif // QMPPLUGIN_H diff --git a/qmidiplayer-desktop/qmppresetselect.cpp b/qmidiplayer-desktop/qmppresetselect.cpp index 8c28fe6..52b0b66 100644 --- a/qmidiplayer-desktop/qmppresetselect.cpp +++ b/qmidiplayer-desktop/qmppresetselect.cpp @@ -95,11 +95,11 @@ void qmpPresetSelector::on_pbOk_clicked() int b,p; b=ui->lwBankSelect->currentItem()->text().toInt(); p=ui->lwPresetSelect->currentItem()->text().split(' ').first().toInt(); - QString s=qmpSettingsWindow::getSettingsIntf()->value("Audio/BankSelect","CC#0").toString(); - if(s=="CC#32"){ + std::string s=qmpMainWindow::getInstance()->getSettings()->getOptionEnumIntOptName("FluidSynth/BankSelect"); + if(s=="XG"){ if(b==128)b=127<<7; } - else if(s=="CC#0")b<<=7; + else if(s=="GS")b<<=7; plyr->setChannelPreset(ch,b,p); } qmpMainWindow::getInstance()->invokeCallback("preset.set",nullptr); diff --git a/qmidiplayer-desktop/qmpsettings.cpp b/qmidiplayer-desktop/qmpsettings.cpp new file mode 100644 index 0000000..134b73b --- /dev/null +++ b/qmidiplayer-desktop/qmpsettings.cpp @@ -0,0 +1,233 @@ +#include "qmpsettings.hpp" +#include + +QSettings* qmpSettings::settings=nullptr; +qmpSettings::qmpSettings() +{ + qRegisterMetaTypeStreamOperators>(); + settings=new QSettings(QStandardPaths::writableLocation(QStandardPaths::StandardLocation::ConfigLocation)+QString("/qmprc"),QSettings::IniFormat); +} + +qmpSettings::~qmpSettings() +{ + delete settings; + settings=nullptr; +} + +void qmpSettings::registerOptionInt(std::string tab,std::string desc,std::string key,int min,int max,int defaultval) +{ + optionlist.push_back(key); + options[key]=qmpOption(tab,desc,qmpOption::ParameterType::parameter_int,nullptr,defaultval,min,max); +} +int qmpSettings::getOptionInt(std::string key) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_int) + return settings->value(QString(key.c_str()),options[key].defaultval).toInt(); + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + return options[key].defaultval.toInt(); +} +void qmpSettings::setOptionInt(std::string key,int val) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_int) + settings->setValue(QString(key.c_str()),val); + else + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + //call qmpSettingsWindow::load(key)? +} + +void qmpSettings::registerOptionUint(std::string tab,std::string desc,std::string key,unsigned min, unsigned max,unsigned defaultval) +{ + optionlist.push_back(key); + options[key]=qmpOption(tab,desc,qmpOption::ParameterType::parameter_uint,nullptr,defaultval,min,max); +} +unsigned qmpSettings::getOptionUint(std::string key) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_uint) + return settings->value(QString(key.c_str()),options[key].defaultval).toUInt(); + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + return options[key].defaultval.toUInt(); +} +void qmpSettings::setOptionUint(std::string key,unsigned val) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_uint) + settings->setValue(QString(key.c_str()),val); + else + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); +} + +void qmpSettings::registerOptionBool(std::string tab,std::string desc,std::string key,bool defaultval) +{ + optionlist.push_back(key); + options[key]=qmpOption(tab,desc,qmpOption::ParameterType::parameter_bool,nullptr,defaultval); +} +bool qmpSettings::getOptionBool(std::string key) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_bool) + return settings->value(QString(key.c_str()),options[key].defaultval).toBool(); + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + return options[key].defaultval.toBool(); +} +void qmpSettings::setOptionBool(std::string key,bool val) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_bool) + settings->setValue(QString(key.c_str()),val); + else + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); +} + +void qmpSettings::registerOptionDouble(std::string tab, std::string desc, std::string key, double min, double max, double defaultval) +{ + optionlist.push_back(key); + options[key]=qmpOption(tab,desc,qmpOption::ParameterType::parameter_double,nullptr,defaultval,min,max); +} +double qmpSettings::getOptionDouble(std::string key) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_double) + return settings->value(QString(key.c_str()),options[key].defaultval).toDouble(); + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + return options[key].defaultval.toDouble(); +} +void qmpSettings::setOptionDouble(std::string key,double val) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_double) + settings->setValue(QString(key.c_str()),val); + else + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); +} + +void qmpSettings::registerOptionString(std::string tab,std::string desc,std::string key,std::string defaultval,bool is_url) +{ + optionlist.push_back(key); + options[key]=qmpOption(tab,desc, + is_url?qmpOption::ParameterType::parameter_url:qmpOption::ParameterType::parameter_str, + nullptr,QString(defaultval.c_str())); +} +std::string qmpSettings::getOptionString(std::string key) +{ + if(options.find(key)!=options.end()&& + (options[key].type==qmpOption::ParameterType::parameter_str||options[key].type==qmpOption::ParameterType::parameter_url)) + return settings->value(QString(key.c_str()),options[key].defaultval).toString().toStdString(); + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + return options[key].defaultval.toString().toStdString(); +} +void qmpSettings::setOptionString(std::string key,std::string val) +{ + if(options.find(key)!=options.end()&& + (options[key].type==qmpOption::ParameterType::parameter_str||options[key].type==qmpOption::ParameterType::parameter_url)) + settings->setValue(QString(key.c_str()),QString(val.c_str())); + else + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); +} + +void qmpSettings::registerOptionEnumInt(std::string tab,std::string desc,std::string key,std::vector enumlist,int defaultval) +{ + optionlist.push_back(key); + options[key]=qmpOption(tab,desc,qmpOption::ParameterType::parameter_enum,nullptr,defaultval); + options[key].enumlist=enumlist; +} +int qmpSettings::getOptionEnumInt(std::string key) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_enum) + { + std::string curitm=settings->value(QString(key.c_str()),options[key].defaultval).toString().toStdString(); + auto curidx=std::find(options[key].enumlist.begin(),options[key].enumlist.end(),curitm); + if(curidx!=options[key].enumlist.end()) + return static_cast(curidx-options[key].enumlist.begin()); + else + { + qWarning("Invalid value set for option \"%s\".",key.c_str()); + return options[key].defaultval.toInt(); + } + } + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + return options[key].defaultval.toInt(); +} + +std::string qmpSettings::getOptionEnumIntOptName(std::string key) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_enum) + { + std::string curitm=settings->value(QString(key.c_str()),options[key].defaultval).toString().toStdString(); + auto curidx=std::find(options[key].enumlist.begin(),options[key].enumlist.end(),curitm); + if(curidx!=options[key].enumlist.end()) + return curitm; + else + { + qWarning("Invalid value set for option \"%s\".",key.c_str()); + return options[key].enumlist[static_cast(options[key].defaultval.toInt())]; + } + } + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + return options[key].enumlist[static_cast(options[key].defaultval.toInt())]; +} +void qmpSettings::setOptionEnumInt(std::string key,int val) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_enum) + { + if(static_cast(val)setValue(QString(key.c_str()),QString(options[key].enumlist[static_cast(val)].c_str())); + else + qWarning("Trying to set invalid value for option \"%s\".",key.c_str()); + } + else + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); +} + +void qmpSettings::setOptionEnumIntOptName(std::string key,std::string valname) +{ + if(options.find(key)!=options.end()&&options[key].type==qmpOption::ParameterType::parameter_enum) + { + auto curidx=std::find(options[key].enumlist.begin(),options[key].enumlist.end(),valname); + if(curidx!=options[key].enumlist.end()) + settings->setValue(QString(key.c_str()),QString(valname.c_str())); + else + qWarning("Trying to set invalid value for option \"%s\".",key.c_str()); + } + else + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); +} + +void qmpSettings::registerOptionCustom(std::string tab,std::string desc,std::string key,void* widget, void* defaultval,std::function save_func,std::function load_func) +{ + optionlist.push_back(key); + options[key]=qmpOption(tab,desc,qmpOption::parameter_custom, + static_cast(widget), + *static_cast(defaultval), + QVariant(),QVariant(),save_func,load_func); +} +void* qmpSettings::getOptionCustom(std::string key) +{ + if(options.find(key)!=options.end()||options[key].type!=qmpOption::ParameterType::parameter_custom) + return static_cast(new QVariant(settings->value(QString(key.c_str()),options[key].defaultval))); + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); + return nullptr; +} +void qmpSettings::setOptionCustom(std::string key,void *val) +{ + if(options.find(key)!=options.end()||options[key].type!=qmpOption::ParameterType::parameter_custom) + settings->setValue(QString(key.c_str()),*static_cast(val)); + else + qWarning("Unregistered option or mismatching option type: %s.",key.c_str()); +} + +void qmpSettings::setOptionRaw(QString key,QVariant val) +{ + settings->setValue(key,val); +} + +QVariant qmpSettings::getOptionRaw(QString key,QVariant defval) +{ + return settings->value(key,defval); +} + +QDataStream &operator<<(QDataStream &out,const QPair &o) +{ + out<>(QDataStream &in,QPair &o) +{ + in>>o.first>>o.second; + return in; +} diff --git a/qmidiplayer-desktop/qmpsettings.hpp b/qmidiplayer-desktop/qmpsettings.hpp new file mode 100644 index 0000000..ff46970 --- /dev/null +++ b/qmidiplayer-desktop/qmpsettings.hpp @@ -0,0 +1,88 @@ +#ifndef QMPSETTINGS_H +#define QMPSETTINGS_H + +#include +#include +#include +#include +#include +#include + +struct qmpOption +{ + enum ParameterType{ + parameter_int=0, + parameter_uint, + parameter_bool, + parameter_double, + parameter_str, + parameter_enum, + parameter_url, + parameter_custom=0x100 + }; + + std::string tab; + std::string desc; + ParameterType type; + QWidget* widget; + QVariant defaultval,minv,maxv; + std::function save_func; + std::function load_func; + std::vector enumlist; + + qmpOption():widget(nullptr){} + qmpOption(std::string _tab,std::string _desc, + ParameterType _t,QWidget* _w=nullptr, + QVariant _def=QVariant(),QVariant _min=QVariant(),QVariant _max=QVariant(), + std::function _save=nullptr,std::function _load=nullptr): + tab(_tab), + desc(_desc), + type(_t), + widget(_w), + defaultval(_def), + minv(_min), + maxv(_max), + save_func(_save), + load_func(_load){} +}; +class qmpSettings +{ + public: + qmpSettings(); + ~qmpSettings(); + void registerOptionInt(std::string tab,std::string desc,std::string key,int min,int max,int defaultval); + int getOptionInt(std::string key); + void setOptionInt(std::string key,int val); + void registerOptionUint(std::string tab,std::string desc,std::string key,unsigned min,unsigned max,unsigned defaultval); + unsigned getOptionUint(std::string key); + void setOptionUint(std::string key,unsigned val); + void registerOptionBool(std::string tab,std::string desc,std::string key,bool defaultval); + bool getOptionBool(std::string key); + void setOptionBool(std::string key,bool val); + void registerOptionDouble(std::string tab,std::string desc,std::string key,double min,double max,double defaultval); + double getOptionDouble(std::string key); + void setOptionDouble(std::string key,double val); + void registerOptionString(std::string tab,std::string desc,std::string key,std::string defaultval,bool is_url); + std::string getOptionString(std::string key); + void setOptionString(std::string key,std::string val); + void registerOptionEnumInt(std::string tab,std::string desc,std::string key,std::vector enumlist,int defaultval); + int getOptionEnumInt(std::string key); + std::string getOptionEnumIntOptName(std::string key); + void setOptionEnumInt(std::string key,int val); + void setOptionEnumIntOptName(std::string key,std::string valname); + void registerOptionCustom(std::string tab,std::string desc,std::string key,void* widget,void* defaultval,std::function save_func,std::function load_func); + void* getOptionCustom(std::string key); + void setOptionCustom(std::string key,void* val); + + void setOptionRaw(QString key,QVariant val); + QVariant getOptionRaw(QString key,QVariant defval=QVariant()); + + private: + static QSettings *settings; + std::map options; + std::vector optionlist; + + friend class qmpSettingsWindow; +}; + +#endif diff --git a/qmidiplayer-desktop/qmpsettingswindow.cpp b/qmidiplayer-desktop/qmpsettingswindow.cpp index 17e16bf..fe75b76 100644 --- a/qmidiplayer-desktop/qmpsettingswindow.cpp +++ b/qmidiplayer-desktop/qmpsettingswindow.cpp @@ -1,51 +1,45 @@ -#include #include #include #include #include #include #include +#include +#include +#include #include "qmpsettingswindow.hpp" #include "qmpdeviceprioritydialog.hpp" #include "ui_qmpsettingswindow.h" #include "qmpmainwindow.hpp" -QSettings* qmpSettingsWindow::settings=nullptr; - void qmpFluidForEachOpt(void* data,const char*,const char* option) { QComboBox *pcb=(QComboBox*)data; pcb->addItem(option); } -qmpSettingsWindow::qmpSettingsWindow(QWidget *parent) : +qmpSettingsWindow::qmpSettingsWindow(qmpSettings *qmpsettings,QWidget *parent) : QDialog(parent), ui(new Ui::qmpSettingsWindow) { ui->setupUi(this);customOptions.clear();customOptPages.clear(); connect(this,&qmpSettingsWindow::dialogClosing,(qmpMainWindow*)parent,&qmpMainWindow::dialogClosed); - settings=new QSettings(QStandardPaths::writableLocation(QStandardPaths::StandardLocation::ConfigLocation)+QString("/qmprc"),QSettings::IniFormat); - settingsInit(); - ui->pbAdd->setIcon(QIcon(getThemedIcon(":/img/add.svg"))); - ui->pbRemove->setIcon(QIcon(getThemedIcon(":/img/remove.svg"))); - ui->pbDown->setIcon(QIcon(getThemedIcon(":/img/down.svg"))); - ui->pbUp->setIcon(QIcon(getThemedIcon(":/img/up.svg"))); - cw=new qmpCustomizeWindow(this); + settings=qmpsettings; + cwt=new qmpCustomizeWindow(this); + cwa=new qmpCustomizeWindow(this); dps=new qmpDevPropDialog(this); devpriod=new qmpDevicePriorityDialog(this); } qmpSettingsWindow::~qmpSettingsWindow() { - delete cw;delete dps; - delete settings;settings=nullptr; delete ui; } void qmpSettingsWindow::closeEvent(QCloseEvent *event) { setVisible(false); - settings->sync(); + loadOption(); emit dialogClosing(); event->accept(); } @@ -57,336 +51,53 @@ void qmpSettingsWindow::hideEvent(QHideEvent *event) void qmpSettingsWindow::on_buttonBox_accepted() { - settingsUpdate(); + saveOption(); qmpMainWindow::getInstance()->setupWidget(); emit dialogClosing(); } void qmpSettingsWindow::on_buttonBox_rejected() { - settingsInit(); + loadOption(); emit dialogClosing(); } -void qmpSettingsWindow::settingsInit() -{ - fluid_settings_t *fsettings=new_fluid_settings(); - - settings->setValue("Midi/DisableMapping",settings->value("Midi/DisableMapping",0)); - ui->cbDisableMapping->setChecked(settings->value("Midi/DisableMapping",0).toInt()); - - settings->setValue("Midi/SendSysEx",settings->value("Midi/SendSysEx",1)); - ui->cbSendSysx->setChecked(settings->value("Midi/SendSysEx",1).toInt()); - - settings->setValue("Midi/WaitVoice",settings->value("Midi/WaitVoice",1)); - ui->cbWaitVoice->setChecked(settings->value("Midi/WaitVoice",1).toInt()); - - int selected=-1; - for(int i=0;icbEncoding->count();++i) - if(ui->cbEncoding->itemText(i)==settings->value("Midi/TextEncoding","Unicode").toString()) - {selected=i;break;} - if(~selected)ui->cbEncoding->setCurrentIndex(selected); - settings->setValue("Midi/TextEncoding",ui->cbEncoding->currentText()); - - fluid_settings_foreach_option(fsettings,"audio.driver",(void*)ui->cbAudioDrv,qmpFluidForEachOpt); - selected=-1; - for(int i=0;icbAudioDrv->count();++i) - if(ui->cbAudioDrv->itemText(i)==settings->value("Audio/Driver","pulseaudio").toString()) - {selected=i;break;} - if(~selected)ui->cbAudioDrv->setCurrentIndex(selected); - settings->setValue("Audio/Driver",ui->cbAudioDrv->currentText()); - -#ifdef _WIN32 -#define DefBufSize 256 -#else -#define DefBufSize 128 -#endif - selected=-1; - for(int i=0;icbBufSize->count();++i) - if(ui->cbBufSize->itemText(i).toInt()==settings->value("Audio/BufSize",DefBufSize).toInt()) - {selected=i;break;} - if(~selected)ui->cbBufSize->setCurrentIndex(selected); - else if(settings->value("Audio/BufSize",DefBufSize).toInt()>=64&&settings->value("Audio/BufSize",DefBufSize).toInt()<=8192) - ui->cbBufSize->setCurrentText(settings->value("Audio/BufSize",DefBufSize).toString()); - else ui->cbBufSize->setCurrentText(QString::number(DefBufSize)); - settings->setValue("Audio/BufSize",ui->cbBufSize->currentText().toInt()); -#undef DefBufSize - -#ifdef _WIN32 -#define DefBufCnt 8 -#else -#define DefBufCnt 2 -#endif - selected=-1; - for(int i=0;icbBufCnt->count();++i) - if(ui->cbBufCnt->itemText(i).toInt()==settings->value("Audio/BufCnt",DefBufCnt).toInt()) - {selected=i;break;} - if(~selected)ui->cbBufCnt->setCurrentIndex(selected); - else if(settings->value("Audio/BufCnt",DefBufCnt).toInt()>=2&&settings->value("Audio/BufCnt",DefBufCnt).toInt()<=64) - ui->cbBufCnt->setCurrentText(settings->value("Audio/BufCnt",DefBufCnt).toString()); - else ui->cbBufCnt->setCurrentText(QString::number(DefBufCnt)); - settings->setValue("Audio/BufCnt",ui->cbBufCnt->currentText().toInt()); -#undef DefBufCnt - - selected=-1; - for(int i=0;icbFormat->count();++i) - if(ui->cbFormat->itemText(i)==settings->value("Audio/Format","16bits").toString()) - {selected=i;break;} - if(~selected)ui->cbFormat->setCurrentIndex(selected); - settings->setValue("Audio/Format",ui->cbFormat->currentText()); - - selected=-1; - for(int i=0;icbFrequency->count();++i) - if(ui->cbFormat->itemText(i).toInt()==settings->value("Audio/Frequency",48000).toInt()) - {selected=i;break;} - if(~selected)ui->cbFrequency->setCurrentIndex(selected); - settings->setValue("Audio/Frequency",ui->cbFrequency->currentText()); - - ui->sbPolyphony->setValue(settings->value("Audio/Polyphony",2048).toInt()); - if(ui->sbPolyphony->value()<1||ui->sbPolyphony->value()>65535)ui->sbPolyphony->setValue(2048); - settings->setValue("Audio/Polyphony",ui->sbPolyphony->value()); - - ui->sbCPUCores->setValue(settings->value("Audio/Threads",1).toInt()); - if(ui->sbCPUCores->value()<1||ui->sbCPUCores->value()>256)ui->sbCPUCores->setValue(1); - settings->setValue("Audio/Threads",ui->sbCPUCores->value()); - - settings->setValue("Audio/AutoBS",settings->value("Audio/AutoBS",1)); - ui->cbAutoBS->setChecked(settings->value("Audio/AutoBS",1).toInt()); - ui->lbBSMode->setText(ui->cbAutoBS->isChecked()?"Fallback bank select mode":"Bank select mode"); - - selected=-1; - for(int i=0;icbBSMode->count();++i) - if(ui->cbBSMode->itemText(i)==settings->value("Audio/BankSelect","CC#0").toString()) - {selected=i;break;} - if(~selected)ui->cbBSMode->setCurrentIndex(selected); - settings->setValue("Audio/BankSelect",ui->cbBSMode->currentText()); - settings->setValue("Audio/Gain",settings->value("Audio/Gain",50)); - - QList sflist=settings->value("Audio/SoundFonts",QList{}).toList(); - ui->twSoundfont->clear(); - for(int i=0;itwSoundfont->insertRow(i); - QTableWidgetItem *sfn,*sfe; - QString sf=sflist[i].toString(); - bool enabled=!sf.startsWith('#'); - if(!enabled)sf=sf.mid(1); - ui->twSoundfont->setItem(i,1,sfn=new QTableWidgetItem(sf)); - ui->twSoundfont->setItem(i,0,sfe=new QTableWidgetItem()); - sfn->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable); - sfe->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable|Qt::ItemFlag::ItemIsUserCheckable); - sfe->setCheckState(enabled?Qt::CheckState::Checked:Qt::CheckState::Unchecked); - } - ui->twSoundfont->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::ResizeToContents); - QStringList qs{"E","Path"}; - ui->twSoundfont->setHorizontalHeaderLabels(qs); - - settings->setValue("Behavior/RestorePlaylist",settings->value("Behavior/RestorePlaylist",0)); - ui->cbRestorePlaylist->setChecked(settings->value("Behavior/RestorePlaylist",0).toInt()); - - settings->setValue("Behavior/LoadFolder",settings->value("Behavior/LoadFolder",0)); - ui->cbLoadFolder->setChecked(settings->value("Behavior/LoadFolder",0).toInt()); - - settings->setValue("Behavior/DialogStatus",settings->value("Behavior/DialogStatus",1)); - ui->cbDialogStatus->setChecked(settings->value("Behavior/DialogStatus",1).toInt()); - - settings->setValue("Behavior/SaveEfxParam",settings->value("Behavior/SaveEfxParam",1)); - ui->cbSaveEfxParam->setChecked(settings->value("Behavior/SaveEfxParam",1).toInt()); - - settings->setValue("Behavior/SingleInstance",settings->value("Behavior/SingleInstance",0)); - ui->cbPersistentfs->setChecked(settings->value("Behavior/SingleInstance",0).toInt()); - - settings->setValue("Behavior/ShowButtonLabel",settings->value("Behavior/ShowButtonLabel",0)); - ui->cbShowLabel->setChecked(settings->value("Behavior/ShowButtonLabel",0).toInt()); - - settings->setValue("Behavior/IconTheme",settings->value("Behavior/IconTheme",0)); - ui->cbIconTheme->setCurrentIndex(settings->value("Behavior/IconTheme",0).toInt()); - - settings->sync(); - delete_fluid_settings(fsettings); -} - -void qmpSettingsWindow::settingsUpdate() -{ - settings->setValue("Midi/DisableMapping",ui->cbDisableMapping->isChecked()?1:0); - - settings->setValue("Midi/SendSysEx",ui->cbSendSysx->isChecked()?1:0); - - settings->setValue("Midi/WaitVoice",ui->cbWaitVoice->isChecked()?1:0); - - settings->setValue("Midi/TextEncoding",ui->cbEncoding->currentText()); - - settings->setValue("Audio/Driver",ui->cbAudioDrv->currentText()); - - settings->setValue("Audio/BufSize",ui->cbBufSize->currentText().toInt()); - - settings->setValue("Audio/BufCnt",ui->cbBufCnt->currentText().toInt()); - - settings->setValue("Audio/Format",ui->cbFormat->currentText()); - - settings->setValue("Audio/Frequency",ui->cbFrequency->currentText()); - - settings->setValue("Audio/Polyphony",ui->sbPolyphony->value()); - - settings->setValue("Audio/Threads",ui->sbCPUCores->value()); - - settings->setValue("Audio/AutoBS",ui->cbAutoBS->isChecked()?1:0); - - settings->setValue("Audio/BankSelect",ui->cbBSMode->currentText()); - - QList sflist; - for(int i=0;itwSoundfont->rowCount();++i) - { - QString sfs=ui->twSoundfont->item(i,1)->text(); - if(ui->twSoundfont->item(i,0)->checkState()==Qt::CheckState::Unchecked)sfs="#"+sfs; - sflist.push_back(sfs); - } - settings->setValue("Audio/SoundFonts",sflist); - - settings->setValue("Behavior/RestorePlaylist",ui->cbRestorePlaylist->isChecked()?1:0); - - settings->setValue("Behavior/LoadFolder",ui->cbLoadFolder->isChecked()?1:0); - - settings->setValue("Behavior/DialogStatus",ui->cbDialogStatus->isChecked()?1:0); - - settings->setValue("Behavior/SingleInstance",ui->cbPersistentfs->isChecked()?1:0); - - settings->setValue("Behavior/ShowButtonLabel",ui->cbShowLabel->isChecked()?1:0); - - settings->setValue("Behavior/IconTheme",ui->cbIconTheme->currentIndex()); - - if(!ui->cbDialogStatus->isChecked()) - { - settings->remove("DialogStatus/MainW"); - settings->remove("DialogStatus/PListW"); - settings->remove("DialogStatus/PListWShown"); - settings->remove("DialogStatus/ChnlW"); - settings->remove("DialogStatus/ChnlWShown"); - settings->remove("DialogStatus/EfxW"); - settings->remove("DialogStatus/EfxWShown"); - settings->remove("DialogStatus/FileDialogPath"); - } - - settings->setValue("Behavior/SaveEfxParam",ui->cbSaveEfxParam->isChecked()?1:0); - if(!ui->cbSaveEfxParam->isChecked()) - { - settings->remove("Effects/ChorusEnabled"); - settings->remove("Effects/ReverbEnabled"); - settings->remove("Effects/ReverbRoom"); - settings->remove("Effects/ReverbDamp"); - settings->remove("Effects/ReverbWidth"); - settings->remove("Effects/ReverbLevel"); - - settings->remove("Effects/ChorusFeedbk"); - settings->remove("Effects/ChorusLevel"); - settings->remove("Effects/ChorusRate"); - settings->remove("Effects/ChorusDepth"); - settings->remove("Effects/ChorusType"); - } - - for(int i=0;itwPluginList->rowCount();++i) - settings->setValue( - QString("PluginSwitch/")+ui->twPluginList->item(i,1)->text(), - ui->twPluginList->item(i,0)->checkState()==Qt::CheckState::Checked?1:0); - updateCustomOptions(); - settings->sync(); -} - -void qmpSettingsWindow::on_cbBufSize_currentTextChanged(const QString &s) -{ - if(s.toInt()<64||s.toInt()>8192)ui->cbBufSize->setCurrentIndex(1); -} - -void qmpSettingsWindow::on_cbBufCnt_currentTextChanged(const QString &s) -{ - if(s.toInt()<2||s.toInt()>64)ui->cbBufCnt->setCurrentIndex(1); -} - -void qmpSettingsWindow::on_pbAdd_clicked() -{ - QStringList sl=QFileDialog::getOpenFileNames(this,"Add File","","SoundFont files (*.sf2)"); - for(int i=0;itwSoundfont->insertRow(ui->twSoundfont->rowCount()); - QTableWidgetItem *sfn,*sfe; - ui->twSoundfont->setItem(ui->twSoundfont->rowCount()-1,1,sfn=new QTableWidgetItem(sl[i])); - ui->twSoundfont->setItem(ui->twSoundfont->rowCount()-1,0,sfe=new QTableWidgetItem()); - sfn->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable); - sfe->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable|Qt::ItemFlag::ItemIsUserCheckable); - } -} - -void qmpSettingsWindow::on_pbRemove_clicked() -{ - QList sl=ui->twSoundfont->selectedItems(); - for(int i=0;itwSoundfont->removeRow(ui->twSoundfont->row(sl[i])); - } -} - -void qmpSettingsWindow::on_pbUp_clicked() -{ - int cid=ui->twSoundfont->currentRow();if(!cid)return; - QTableWidgetItem *ci=ui->twSoundfont->takeItem(cid,1); - QTableWidgetItem *ce=ui->twSoundfont->takeItem(cid,0); - ui->twSoundfont->removeRow(cid); - ui->twSoundfont->insertRow(cid-1); - ui->twSoundfont->setItem(cid-1,0,ce); - ui->twSoundfont->setItem(cid-1,1,ci); - ui->twSoundfont->setCurrentCell(cid-1,1); -} - -void qmpSettingsWindow::on_pbDown_clicked() -{ - int cid=ui->twSoundfont->currentRow();if(cid==ui->twSoundfont->rowCount()-1)return; - QTableWidgetItem *ci=ui->twSoundfont->takeItem(cid,1); - QTableWidgetItem *ce=ui->twSoundfont->takeItem(cid,0); - ui->twSoundfont->removeRow(cid); - ui->twSoundfont->insertRow(cid+1); - ui->twSoundfont->setItem(cid+1,0,ce); - ui->twSoundfont->setItem(cid+1,1,ci); - ui->twSoundfont->setCurrentCell(cid+1,1); -} - -void qmpSettingsWindow::on_cbAutoBS_stateChanged() -{ - ui->lbBSMode->setText(ui->cbAutoBS->isChecked()?"Fallback bank select mode":"Bank select mode"); -} - void qmpSettingsWindow::updatePluginList(qmpPluginManager *pmgr) { std::vector *plugins=pmgr->getPlugins(); + QVariant *data=static_cast(settings->getOptionCustom("DisabledPlugins")); + QList disabled_plugins_l=static_cast(data)->toList(); + delete data; + std::set disabled_plugins_s; + for(auto &i:disabled_plugins_l) + disabled_plugins_s.insert(i.toString().toStdString()); for(unsigned i=0;isize();++i) { - ui->twPluginList->insertRow(i); - QTableWidgetItem *icb; - ui->twPluginList->setItem(i,0,icb=new QTableWidgetItem()); - bool enabled=settings->value(QString("PluginSwitch/")+QString(plugins->at(i).name.c_str()),1).toInt(); - icb->setCheckState(enabled?Qt::CheckState::Checked:Qt::CheckState::Unchecked); - icb->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable|Qt::ItemFlag::ItemIsUserCheckable); + bool enabled=disabled_plugins_s.find(plugins->at(i).name)==disabled_plugins_s.end(); plugins->at(i).enabled=enabled; - ui->twPluginList->setItem(i,1,new QTableWidgetItem(plugins->at(i).name.c_str())); - ui->twPluginList->setItem(i,2,new QTableWidgetItem(plugins->at(i).version.c_str())); - ui->twPluginList->setItem(i,3,new QTableWidgetItem(plugins->at(i).path.c_str())); - for(int j=1;j<=3;++j) - ui->twPluginList->item(i,j)->setFlags(ui->twPluginList->item(i,j)->flags()^Qt::ItemIsEditable); } - ui->twPluginList->setColumnWidth(0,22); - ui->twPluginList->setColumnWidth(1,192); - ui->twPluginList->setColumnWidth(2,64); - ui->twPluginList->setColumnWidth(3,128); } void qmpSettingsWindow::postInit() { + setupWidgets(); int sf=0; - for(int i=0;itwSoundfont->rowCount();++i) - if(ui->twSoundfont->item(i,0)->checkState()==Qt::CheckState::Checked)++sf; + QVariant *data=static_cast(settings->getOptionCustom("FluidSynth/SoundFonts")); + for(auto i:data->toList()) + if(!i.toString().startsWith('#')) + { + sf=1; + break; + } + delete data; std::string selecteddev; std::vector devs=qmpMainWindow::getInstance()->getPlayer()->getMidiOutDevices(); std::set devset; for(auto dev:devs)devset.insert(dev); - for(auto setdev:qmpSettingsWindow::getSettingsIntf()->value("Midi/DevicePriority",QList{"Internal FluidSynth"}).toList()) + QVariant *devpriov=static_cast(qmpMainWindow::getInstance()->getSettings()->getOptionCustom("Midi/DevicePriority")); + QList devprio=devpriov->toList(); + delete devpriov; + for(auto &setdev:devprio) if(devset.find(setdev.toString().toStdString())!=devset.end()) { selecteddev=setdev.toString().toStdString(); @@ -400,338 +111,458 @@ void qmpSettingsWindow::postInit() "Would you like to setup soundfonts now? You may have to reload the internal synth afterwards."))==QMessageBox::Yes) { show(); - ui->tabWidget->setCurrentWidget(ui->tab_3); + ui->tabWidget->setCurrentWidget(qobject_cast(pageForTab("SoundFonts")->parent())); } } - devpriod->setupRegisteredDevices(); } -void qmpSettingsWindow::updateCustomOptions() -{ - for(auto i=customOptions.begin();i!=customOptions.end();++i) - switch(i->second.type) - { - case 0: - { - QSpinBox* sb=(QSpinBox*)i->second.widget;if(!i->second.widget)break; - settings->setValue(QString(i->first.c_str()),sb->value()); - break; - } - case 1: - { - QHexSpinBox* sb=(QHexSpinBox*)i->second.widget;if(!i->second.widget)break; - int v=sb->value(); - settings->setValue(QString(i->first.c_str()),*reinterpret_cast(&v)); - break; - } - case 2: - { - if(!i->second.widget)break; - settings->setValue(QString(i->first.c_str()),((QCheckBox*)i->second.widget)->isChecked()?1:0); - break; +void qmpSettingsWindow::registerCustomizeWidgetOptions() +{ + QPushButton *pbCustomizeToolbar=new QPushButton(tr("Customize...")); + QPushButton *pbCustomizeActions=new QPushButton(tr("Customize...")); + QVariant toolbar_def_val=QList({"Channel","Playlist","Effects","Visualization"}); + QVariant actions_def_val=QList({"FileInfo","Render","Panic","ReloadSynth"}); + settings->registerOptionCustom("Behavior","Customize toolbar","Behavior/Toolbar",pbCustomizeToolbar,&toolbar_def_val,std::bind(&qmpCustomizeWindow::save,cwt),std::bind(&qmpCustomizeWindow::load,cwt,std::placeholders::_1)); + settings->registerOptionCustom("Behavior","Customize actions","Behavior/Actions",pbCustomizeActions,&actions_def_val,std::bind(&qmpCustomizeWindow::save,cwa),std::bind(&qmpCustomizeWindow::load,cwa,std::placeholders::_1)); + connect(pbCustomizeToolbar,&QPushButton::clicked,[this]{loadOption("Behavior/Toolbar");cwt->show();}); + connect(pbCustomizeActions,&QPushButton::clicked,[this]{loadOption("Behavior/Actions");cwa->show();}); + connect(cwt,&QDialog::accepted,[this]{saveOption("Behavior/Toolbar");qmpMainWindow::getInstance()->setupWidget();}); + connect(cwa,&QDialog::accepted,[this]{saveOption("Behavior/Actions");qmpMainWindow::getInstance()->setupWidget();}); + connect(cwt,&QDialog::rejected,[this]{loadOption("Behavior/Toolbar");}); + connect(cwa,&QDialog::rejected,[this]{loadOption("Behavior/Actions");}); + qmpMainWindow::getInstance()->setupWidget(); +} + +void qmpSettingsWindow::registerSoundFontOption() +{ + QWidget *sfpanel=new QWidget(); + sfpanel->setLayout(new QVBoxLayout); + sfpanel->layout()->setMargin(0); + QTableWidget *twsf=new QTableWidget(); + twsf->setColumnCount(2); + twsf->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::ResizeToContents); + twsf->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); + twsf->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows); + twsf->setHorizontalHeaderLabels({tr("E"),tr("Path")}); + twsf->setHorizontalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel); + twsf->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel); + sfpanel->layout()->addWidget(twsf); + QWidget *controls=new QWidget(); + controls->setLayout(new QHBoxLayout); + controls->layout()->setMargin(0); + QPushButton *pbsfadd=new QPushButton(style()->standardIcon(QStyle::StandardPixmap::SP_DialogOpenButton),QString()); + QPushButton *pbsfrem=new QPushButton(style()->standardIcon(QStyle::StandardPixmap::SP_DialogDiscardButton),QString()); + QPushButton *pbsfmup=new QPushButton(style()->standardIcon(QStyle::StandardPixmap::SP_ArrowUp),QString()); + QPushButton *pbsfmdn=new QPushButton(style()->standardIcon(QStyle::StandardPixmap::SP_ArrowDown),QString()); + controls->layout()->addWidget(pbsfadd); + controls->layout()->addWidget(pbsfrem); + controls->layout()->addWidget(pbsfmup); + controls->layout()->addWidget(pbsfmdn); + sfpanel->layout()->addWidget(controls); + + connect(pbsfadd,&QPushButton::clicked,[twsf,this]{ + QStringList sl=QFileDialog::getOpenFileNames(this,"Add File","","SoundFont files (*.sf2)"); + for(int i=0;iinsertRow(twsf->rowCount()); + QTableWidgetItem *sfn,*sfe; + twsf->setItem(twsf->rowCount()-1,1,sfn=new QTableWidgetItem(sl[i])); + twsf->setItem(twsf->rowCount()-1,0,sfe=new QTableWidgetItem()); + sfe->setCheckState(Qt::CheckState::Unchecked); + sfn->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable); + sfe->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable|Qt::ItemFlag::ItemIsUserCheckable); } - case 3: + }); + connect(pbsfrem,&QPushButton::clicked,[twsf]{ + QList sl=twsf->selectedItems(); + for(int i=0;iremoveRow(twsf->row(sl[i])); + }); + connect(pbsfmup,&QPushButton::clicked,[twsf]{ + int cid=twsf->currentRow();if(!cid)return; + QTableWidgetItem *ci=twsf->takeItem(cid,1); + QTableWidgetItem *ce=twsf->takeItem(cid,0); + twsf->removeRow(cid); + twsf->insertRow(cid-1); + twsf->setItem(cid-1,0,ce); + twsf->setItem(cid-1,1,ci); + twsf->setCurrentCell(cid-1,1); + }); + connect(pbsfmdn,&QPushButton::clicked,[twsf]{ + int cid=twsf->currentRow();if(cid==twsf->rowCount()-1)return; + QTableWidgetItem *ci=twsf->takeItem(cid,1); + QTableWidgetItem *ce=twsf->takeItem(cid,0); + twsf->removeRow(cid); + twsf->insertRow(cid+1); + twsf->setItem(cid+1,0,ce); + twsf->setItem(cid+1,1,ci); + twsf->setCurrentCell(cid+1,1); + }); + + QVariant sf_def_val=QList(); + auto save_func=[twsf]()->void*{ + QList sflist; + for(int i=0;irowCount();++i) { - QDoubleSpinBox* sb=(QDoubleSpinBox*)i->second.widget;if(!i->second.widget)break; - settings->setValue(QString(i->first.c_str()),sb->value()); - break; + QString sfs=twsf->item(i,1)->text(); + if(twsf->item(i,0)->checkState()==Qt::CheckState::Unchecked) + sfs="#"+sfs; + sflist.push_back(sfs); } - case 4: + return new QVariant(sflist); + }; + auto load_func=[twsf](void* data){ + QList sflist=static_cast(data)->toList(); + twsf->clearContents(); + twsf->setRowCount(0); + for(int i=0;isecond.widget;if(!i->second.widget)break; - settings->setValue(QString(i->first.c_str()),te->text()); - break; + twsf->insertRow(i); + QTableWidgetItem *sfn,*sfe; + QString sf=sflist[i].toString(); + bool enabled=!sf.startsWith('#'); + if(!enabled)sf=sf.mid(1); + twsf->setItem(i,1,sfn=new QTableWidgetItem(sf)); + twsf->setItem(i,0,sfe=new QTableWidgetItem()); + sfn->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable); + sfe->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable|Qt::ItemFlag::ItemIsUserCheckable); + sfe->setCheckState(enabled?Qt::CheckState::Checked:Qt::CheckState::Unchecked); } - case 5: + }; + settings->registerOptionCustom("SoundFonts","","FluidSynth/SoundFonts",sfpanel,&sf_def_val,save_func,load_func); +} + +void qmpSettingsWindow::registerPluginOption(qmpPluginManager *pmgr) +{ + QTableWidget *twplugins=new QTableWidget(); + twplugins->setColumnCount(4); + twplugins->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::ResizeToContents); + twplugins->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); + twplugins->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows); + twplugins->setHorizontalHeaderLabels({tr("E"),tr("Plugin Name"),tr("Version"),tr("Path")}); + twplugins->setHorizontalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel); + twplugins->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel); + QVariant ep_def_val=QList(); + auto save_func=[twplugins,this]()->void*{ + QVariant *data=static_cast(settings->getOptionCustom("DisabledPlugins")); + QList disabled_plugins_ol=static_cast(data)->toList(); + delete data; + std::set disabled_plugins_s; + for(auto &i:disabled_plugins_ol) + disabled_plugins_s.insert(i.toString().toStdString()); + for(int i=0;irowCount();++i) { - QComboBox* cb=(QComboBox*)i->second.widget;if(!i->second.widget)break; - settings->setValue(QString(i->first.c_str()),cb->currentIndex()); - break; + QString pn=twplugins->item(i,1)->text(); + if(twplugins->item(i,0)->checkState()==Qt::CheckState::Unchecked) + disabled_plugins_s.insert(pn.toStdString()); + else + disabled_plugins_s.erase(pn.toStdString()); } - case 6: + QList disabled_plugins; + for(auto &i:disabled_plugins_s) + disabled_plugins.push_back(QString(i.c_str())); + return new QVariant(disabled_plugins); + }; + auto load_func=[twplugins,pmgr](void* data){ + QList disabled_plugins_l=static_cast(data)->toList(); + std::set disabled_plugins; + for(auto i:disabled_plugins_l) + disabled_plugins.insert(i.toString().toStdString()); + + twplugins->clearContents(); + twplugins->setRowCount(0); + + std::vector *plugins=pmgr->getPlugins(); + for(int i=0;static_cast(i)size();++i) { - QFileEdit* fe=(QFileEdit*)i->second.widget;if(!i->second.widget)break; - settings->setValue(QString(i->first.c_str()),fe->text()); - break; + twplugins->insertRow(i); + qmpPlugin &p=plugins->at(static_cast(i)); + QTableWidgetItem *icb; + twplugins->setItem(i,0,icb=new QTableWidgetItem()); + bool enabled=disabled_plugins.find(p.name)==disabled_plugins.end(); + icb->setCheckState(enabled?Qt::CheckState::Checked:Qt::CheckState::Unchecked); + icb->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable|Qt::ItemFlag::ItemIsUserCheckable); + twplugins->setItem(i,1,new QTableWidgetItem(p.name.c_str())); + twplugins->setItem(i,2,new QTableWidgetItem(p.version.c_str())); + twplugins->setItem(i,3,new QTableWidgetItem(p.path.c_str())); + for(int j=1;j<=3;++j) + twplugins->item(i,j)->setFlags(Qt::ItemFlag::ItemIsEnabled|Qt::ItemFlag::ItemIsSelectable); } - } + }; + settings->registerOptionCustom("Plugins","","DisabledPlugins",twplugins,&ep_def_val,save_func,load_func); } -void qmpSettingsWindow::registerOptionInt(std::string tab,std::string desc,std::string key,int min,int max,int defaultval) -{ - customOptions[key].widget=nullptr; - customOptions[key].desc=desc; - customOptions[key].defaultval=defaultval; - customOptions[key].minv=min; - customOptions[key].maxv=max; - customOptions[key].type=0; - if(desc.length()) - { - QGridLayout* page=nullptr; - if(customOptPages[tab])page=customOptPages[tab]; - else - { - QWidget* w=new QWidget; - page=new QGridLayout(w); - w->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->tabWidget->addTab(w,QString(tab.c_str())); - customOptPages[tab]=page; - } - QSpinBox* sb=new QSpinBox(page->parentWidget()); - QLabel* lb=new QLabel(desc.c_str(),page->parentWidget()); - customOptions[key].widget=sb; - sb->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); - lb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - int row=page->rowCount(); - page->addWidget(lb,row,0); - page->addWidget(sb,row,1); - sb->setMaximum(max); - sb->setMinimum(min); - sb->setValue(settings->value(QString(key.c_str()),defaultval).toInt()); - } -} -int qmpSettingsWindow::getOptionInt(std::string key) +void qmpSettingsWindow::registerExtraMidiOptions() { - return settings->value(QString(key.c_str()),customOptions[key].defaultval).toInt(); -} -void qmpSettingsWindow::setOptionInt(std::string key,int val) -{ - settings->setValue(QString(key.c_str()),val); - if(customOptions[key].widget) - ((QSpinBox*)customOptions[key].widget)->setValue(val); + QPushButton *pbDevPrio=new QPushButton("..."); + connect(pbDevPrio,&QPushButton::clicked,[this]{loadOption("Midi/DevicePriority");devpriod->show();}); + connect(devpriod,&QDialog::accepted,[this]{saveOption("Midi/DevicePriority");}); + connect(devpriod,&QDialog::rejected,[this]{loadOption("Midi/DevicePriority");}); + QVariant devprio_def_val=QList({"Internal FluidSynth"}); + settings->registerOptionCustom("MIDI","Select MIDI output devices","Midi/DevicePriority",pbDevPrio,&devprio_def_val,std::bind(&qmpDevicePriorityDialog::save,devpriod),std::bind(&qmpDevicePriorityDialog::load,devpriod,std::placeholders::_1)); + + QPushButton *pbDevProp=new QPushButton("..."); + connect(pbDevProp,&QPushButton::clicked,[this]{loadOption("Midi/DeviceInitializationFiles");dps->show();}); + connect(dps,&QDialog::accepted,[this]{saveOption("Midi/DeviceInitializationFiles");}); + connect(dps,&QDialog::rejected,[this]{loadOption("Midi/DeviceInitializationFiles");}); + QVariant devprop_def_val=QList({}); + settings->registerOptionCustom("MIDI","External MIDI device setup","Midi/DeviceInitializationFiles",pbDevProp,&devprop_def_val,std::bind(&qmpDevPropDialog::save,dps),std::bind(&qmpDevPropDialog::load,dps,std::placeholders::_1)); } -void qmpSettingsWindow::registerOptionUint(std::string tab,std::string desc,std::string key,unsigned min,unsigned max,unsigned defaultval) +void qmpSettingsWindow::saveOption(std::string key) { - customOptions[key].widget=nullptr; - customOptions[key].desc=desc; - customOptions[key].defaultval=defaultval; - customOptions[key].minv=min; - customOptions[key].maxv=max; - customOptions[key].type=1; - if(desc.length()) + auto save_opt=[this](std::string& key)->QVariant { - QGridLayout* page=nullptr; - if(customOptPages[tab])page=customOptPages[tab]; - else + qmpOption &o=settings->options[key]; + QVariant ret; + switch(o.type) { - QWidget* w=new QWidget; - page=new QGridLayout(w); - w->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->tabWidget->addTab(w,QString(tab.c_str())); - customOptPages[tab]=page; + case qmpOption::ParameterType::parameter_int: + { + QSpinBox *sb=qobject_cast(o.widget); + if(sb) + ret=sb->value(); + } + break; + case qmpOption::ParameterType::parameter_uint: + { + QHexSpinBox *sb=qobject_cast(o.widget); + if(sb) + { + int val=sb->value(); + ret=reinterpret_cast(val); + } + } + break; + case qmpOption::ParameterType::parameter_bool: + { + QCheckBox *cb=qobject_cast(o.widget); + if(cb) + ret=cb->isChecked(); + } + break; + case qmpOption::ParameterType::parameter_double: + { + QDoubleSpinBox *sb=qobject_cast(o.widget); + if(sb) + ret=sb->value(); + } + break; + case qmpOption::ParameterType::parameter_str: + { + QLineEdit *le=qobject_cast(o.widget); + if(le) + ret=le->text(); + } + break; + case qmpOption::ParameterType::parameter_enum: + { + QComboBox *cb=qobject_cast(o.widget); + if(cb) + ret=cb->currentText(); + } + break; + case qmpOption::ParameterType::parameter_url: + { + QFileEdit *fe=qobject_cast(o.widget); + if(fe) + ret=fe->text(); + } + break; + default: + if(o.save_func) + { + QVariant* var=static_cast(o.save_func()); + ret=QVariant(*var); + delete var; + } + break; } - QHexSpinBox* sb=new QHexSpinBox(page->parentWidget()); - QLabel* lb=new QLabel(desc.c_str(),page->parentWidget()); - customOptions[key].widget=sb; - sb->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); - lb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - int row=page->rowCount(); - page->addWidget(lb,row,0); - page->addWidget(sb,row,1); - //sb->setMaximum(i(max));sb->setMinimum(i(min)); - sb->setValue(settings->value(QString(key.c_str()),defaultval).toUInt()); + return ret; + }; + if(key.length()) + { + QVariant r=save_opt(key); + if(r.isValid()) + settings->settings->setValue(QString(key.c_str()),r); } -} -unsigned qmpSettingsWindow::getOptionUint(std::string key) -{ - return settings->value(QString(key.c_str()),customOptions[key].defaultval).toUInt(); -} -void qmpSettingsWindow::setOptionUint(std::string key,unsigned val) -{ - settings->setValue(QString(key.c_str()),val); - if(customOptions[key].widget) - ((QHexSpinBox*)customOptions[key].widget)->setValue(val); -} - -void qmpSettingsWindow::registerOptionBool(std::string tab,std::string desc,std::string key,bool defaultval) -{ - customOptions[key].widget=nullptr; - customOptions[key].desc=desc; - customOptions[key].defaultval=defaultval; - customOptions[key].type=2; - if(desc.length()) + else for(std::string& key:settings->optionlist) { - QGridLayout* page=nullptr; - if(customOptPages[tab])page=customOptPages[tab]; - else - { - QWidget* w=new QWidget; - page=new QGridLayout(w); - w->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->tabWidget->addTab(w,QString(tab.c_str())); - customOptPages[tab]=page; - } - QCheckBox* cb=new QCheckBox(desc.c_str(),page->parentWidget()); - customOptions[key].widget=cb; - cb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - int row=page->rowCount(); - page->addWidget(cb,row,0,1,2); - cb->setChecked(settings->value(QString(key.c_str()),(int)defaultval).toInt()); + QVariant r=save_opt(key); + if(r.isValid()) + settings->settings->setValue(QString(key.c_str()),r); } -} -bool qmpSettingsWindow::getOptionBool(std::string key) -{ - return settings->value(QString(key.c_str()),(int)customOptions[key].defaultval.toBool()).toInt(); -} -void qmpSettingsWindow::setOptionBool(std::string key,bool val) -{ - settings->setValue(QString(key.c_str()),val?1:0); - if(customOptions[key].widget) - ((QCheckBox*)customOptions[key].widget)->setChecked(val); + settings->settings->sync(); } -void qmpSettingsWindow::registerOptionDouble(std::string tab,std::string desc,std::string key,double min,double max,double defaultval) +void qmpSettingsWindow::loadOption(std::string key) { - customOptions[key].widget=nullptr; - customOptions[key].desc=desc; - customOptions[key].defaultval=defaultval; - customOptions[key].minv=min; - customOptions[key].maxv=max; - customOptions[key].type=3; - if(desc.length()) + auto load_opt=[this](std::string& key) { - QGridLayout* page=nullptr; - if(customOptPages[tab])page=customOptPages[tab]; - else + qmpOption &o=settings->options[key]; + switch(o.type) { - QWidget* w=new QWidget; - page=new QGridLayout(w); - w->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->tabWidget->addTab(w,QString(tab.c_str())); - customOptPages[tab]=page; + case qmpOption::ParameterType::parameter_int: + { + QSpinBox *sb=qobject_cast(o.widget); + if(sb) + sb->setValue(settings->getOptionInt(key)); + } + break; + case qmpOption::ParameterType::parameter_uint: + { + QHexSpinBox *sb=qobject_cast(o.widget); + if(sb) + sb->setValue(settings->getOptionUint(key)); + } + break; + case qmpOption::ParameterType::parameter_bool: + { + QCheckBox *cb=qobject_cast(o.widget); + if(cb) + cb->setChecked(settings->getOptionBool(key)); + } + break; + case qmpOption::ParameterType::parameter_double: + { + QDoubleSpinBox *sb=qobject_cast(o.widget); + if(sb) + sb->setValue(settings->getOptionDouble(key)); + } + break; + case qmpOption::ParameterType::parameter_str: + { + QLineEdit *le=qobject_cast(o.widget); + if(le) + le->setText(QString(settings->getOptionString(key).c_str())); + } + break; + case qmpOption::ParameterType::parameter_enum: + { + QComboBox *cb=qobject_cast(o.widget); + if(cb) + cb->setCurrentIndex(settings->getOptionEnumInt(key)); + } + break; + case qmpOption::ParameterType::parameter_url: + { + QFileEdit *fe=qobject_cast(o.widget); + if(fe) + fe->setText(QString(settings->getOptionString(key).c_str())); + } + break; + default: + if(o.load_func) + { + void *var=settings->getOptionCustom(key); + o.load_func(var); + delete static_cast(var); + } + break; } - QDoubleSpinBox* sb=new QDoubleSpinBox(page->parentWidget()); - QLabel* lb=new QLabel(desc.c_str(),page->parentWidget()); - customOptions[key].widget=sb; - sb->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); - lb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - int row=page->rowCount(); - page->addWidget(lb,row,0); - page->addWidget(sb,row,1); - sb->setMaximum(max); - sb->setMinimum(min); - sb->setValue(settings->value(QString(key.c_str()),defaultval).toDouble()); - } -} -double qmpSettingsWindow::getOptionDouble(std::string key) -{ - return settings->value(QString(key.c_str()),customOptions[key].defaultval).toDouble(); -} -void qmpSettingsWindow::setOptionDouble(std::string key,double val) -{ - settings->setValue(QString(key.c_str()),val); - if(customOptions[key].widget) - ((QDoubleSpinBox*)customOptions[key].widget)->setValue(val); + }; + if(key.length())load_opt(key); + else for(std::string& key:settings->optionlist) + load_opt(key); } -void qmpSettingsWindow::registerOptionString(std::string tab,std::string desc,std::string key,std::string defaultval,bool ispath) +void qmpSettingsWindow::setupWidgets() { - customOptions[key].widget=nullptr; - customOptions[key].desc=desc; - customOptions[key].defaultval=QString(defaultval.c_str()); - customOptions[key].type=4; - if(ispath)customOptions[key].type=6; - if(desc.length()) + for(std::string& key:settings->optionlist) { - QGridLayout* page=nullptr; - if(customOptPages[tab])page=customOptPages[tab]; - else + if(!settings->options[key].desc.length()&&settings->options[key].type!=qmpOption::ParameterType::parameter_custom) + continue; + QWidget *optw=nullptr; + qmpOption &o=settings->options[key]; + switch(o.type) { - QWidget* w=new QWidget; - page=new QGridLayout(w); - w->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->tabWidget->addTab(w,QString(tab.c_str())); - customOptPages[tab]=page; - } - int row=page->rowCount(); - if(ispath) - { - QFileEdit* fe=new QFileEdit(page->parentWidget()); - fe->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); - customOptions[key].widget=fe; - fe->setText(settings->value(QString(key.c_str()),defaultval.c_str()).toString()); - page->addWidget(fe,row,1); + case qmpOption::ParameterType::parameter_int: + { + QSpinBox *sb=new QSpinBox; + sb->setMinimum(o.minv.toInt()); + sb->setMaximum(o.maxv.toInt()); + sb->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); + optw=sb; + } + break; + case qmpOption::ParameterType::parameter_uint: + { + QHexSpinBox *sb=new QHexSpinBox; + sb->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); + optw=sb; + } + break; + case qmpOption::ParameterType::parameter_bool: + { + QCheckBox *cb=new QCheckBox(QString(o.desc.c_str())); + cb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + optw=cb; + } + break; + case qmpOption::ParameterType::parameter_double: + { + QDoubleSpinBox *sb=new QDoubleSpinBox; + sb->setMinimum(o.minv.toDouble()); + sb->setMaximum(o.maxv.toDouble()); + sb->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); + optw=sb; + } + break; + case qmpOption::ParameterType::parameter_str: + { + QLineEdit* te=new QLineEdit(); + te->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); + optw=te; + } + break; + case qmpOption::ParameterType::parameter_enum: + { + QComboBox* cb=new QComboBox(); + for(std::string& item:o.enumlist)cb->addItem(QString(item.c_str())); + cb->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); + optw=cb; + } + break; + case qmpOption::ParameterType::parameter_url: + { + QFileEdit* fe=new QFileEdit(); + fe->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); + optw=fe; + } + break; + default: + optw=o.widget; + break; } - else + o.widget=optw; + QGridLayout* page=pageForTab(o.tab); + if(o.type==qmpOption::ParameterType::parameter_bool|| + (o.type==qmpOption::parameter_custom&&!o.desc.length())) { - QLineEdit* te=new QLineEdit(page->parentWidget()); - te->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); - customOptions[key].widget=te; - te->setText(settings->value(QString(key.c_str()),defaultval.c_str()).toString()); - page->addWidget(te,row,1); + int row=page->rowCount(); + page->addWidget(o.widget,row,0,1,2); } - QLabel* lb=new QLabel(desc.c_str(),page->parentWidget()); - lb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - page->addWidget(lb,row,0); - } -} -std::string qmpSettingsWindow::getOptionString(std::string key) -{ - return settings->value(QString(key.c_str()),customOptions[key].defaultval).toString().toStdString(); -} -void qmpSettingsWindow::setOptionString(std::string key,std::string val) -{ - settings->setValue(QString(key.c_str()),QString(val.c_str())); - if(customOptions[key].widget) - { - if(customOptions[key].type==4) - ((QLineEdit*)customOptions[key].widget)->setText(val.c_str()); - else if(customOptions[key].type==6) - ((QFileEdit*)customOptions[key].widget)->setText(val.c_str()); - } -} - -void qmpSettingsWindow::registerOptionEnumInt(std::string tab,std::string desc,std::string key,std::vector options,int defaultval) -{ - customOptions[key].widget=nullptr; - customOptions[key].desc=desc; - customOptions[key].defaultval=defaultval; - customOptions[key].type=5; - if(desc.length()) - { - QGridLayout* page=nullptr; - if(customOptPages[tab])page=customOptPages[tab]; else { - QWidget* w=new QWidget; - page=new QGridLayout(w); - w->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - ui->tabWidget->addTab(w,QString(tab.c_str())); - customOptPages[tab]=page; + QLabel* lb=new QLabel(o.desc.c_str(),page->parentWidget()); + lb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + int row=page->rowCount(); + page->addWidget(lb,row,0); + page->addWidget(o.widget,row,1); } - QComboBox* sb=new QComboBox(page->parentWidget()); - QLabel* lb=new QLabel(desc.c_str(),page->parentWidget()); - customOptions[key].widget=sb; - for(unsigned i=0;iaddItem(options[i].c_str()); - sb->setCurrentIndex(settings->value(QString(key.c_str()),defaultval).toInt()); - sb->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); - lb->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - int row=page->rowCount(); - page->addWidget(lb,row,0); - page->addWidget(sb,row,1); - } -} -int qmpSettingsWindow::getOptionEnumInt(std::string key) -{ - return settings->value(QString(key.c_str()),customOptions[key].defaultval).toInt(); -} -void qmpSettingsWindow::setOptionEnumInt(std::string key,int val) -{ - settings->setValue(QString(key.c_str()),val); - if(customOptions[key].widget) - ((QComboBox*)customOptions[key].widget)->setCurrentIndex(val); -} - -void qmpSettingsWindow::on_pbCustomizeTb_clicked() -{ - cw->launch(0); + loadOption(); } -void qmpSettingsWindow::on_pbCustomizeAct_clicked() +QGridLayout* qmpSettingsWindow::pageForTab(std::string tab) { - cw->launch(1); + if(customOptPages.find(tab)!=customOptPages.end()) + return customOptPages[tab]; + QWidget* w=new QWidget; + QGridLayout* page=new QGridLayout(w); + w->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + ui->tabWidget->addTab(w,QString(tab.c_str())); + customOptPages[tab]=page; + return page; } QFileEdit::QFileEdit(QWidget *par):QWidget(par) @@ -752,13 +583,3 @@ void QFileEdit::chooseFile() QString s=QFileDialog::getOpenFileName(nullptr,tr("Select a file"),QFileInfo(text()).dir().absolutePath()); if(s.length())setText(s); } - -void qmpSettingsWindow::on_pbExtDevSetup_clicked() -{ - dps->launch(); -} - -void qmpSettingsWindow::on_pbDevPrio_clicked() -{ - devpriod->show(); -} diff --git a/qmidiplayer-desktop/qmpsettingswindow.hpp b/qmidiplayer-desktop/qmpsettingswindow.hpp index c1ae410..5243ca9 100644 --- a/qmidiplayer-desktop/qmpsettingswindow.hpp +++ b/qmidiplayer-desktop/qmpsettingswindow.hpp @@ -12,6 +12,7 @@ #include #include #include +#include "qmpsettings.hpp" #include "qmpplugin.hpp" #include "qmpcustomizewindow.hpp" #include "qmpdevpropdialog.hpp" @@ -20,13 +21,6 @@ namespace Ui { class qmpSettingsWindow; } -struct qmpCustomOption -{ - QWidget* widget; - std::string desc;int type; - QVariant defaultval,minv,maxv; -}; - class QLineEdit; class QToolButton; class QFileEdit:public QWidget @@ -60,7 +54,7 @@ class QHexSpinBox:public QSpinBox } int valueFromText(const QString &text)const { - return i(text.toUInt(0,16)); + return i(text.toUInt(nullptr,16)); } QValidator::State validate(QString &input,int &pos)const { @@ -74,9 +68,9 @@ class QHexSpinBox:public QSpinBox return QValidator::Acceptable; } inline unsigned int u(int i)const - {return *reinterpret_cast(&i);} + {return reinterpret_cast(i);} inline int i(unsigned int u)const - {return *reinterpret_cast(&u);} + {return reinterpret_cast(u);} }; class qmpDevicePriorityDialog; @@ -86,31 +80,16 @@ class qmpSettingsWindow:public QDialog Q_OBJECT public: - explicit qmpSettingsWindow(QWidget *parent=nullptr); + explicit qmpSettingsWindow(qmpSettings *qmpsettings,QWidget *parent=nullptr); ~qmpSettingsWindow(); void closeEvent(QCloseEvent *event); void hideEvent(QHideEvent *event); - void settingsInit(); void updatePluginList(qmpPluginManager *pmgr); - void registerOptionInt(std::string tab,std::string desc,std::string key,int min,int max,int defaultval); - int getOptionInt(std::string key); - void setOptionInt(std::string key,int val); - void registerOptionUint(std::string tab,std::string desc,std::string key,unsigned min,unsigned max,unsigned defaultval); - unsigned getOptionUint(std::string key); - void setOptionUint(std::string key,unsigned val); - void registerOptionBool(std::string tab,std::string desc,std::string key,bool defaultval); - bool getOptionBool(std::string key); - void setOptionBool(std::string key,bool val); - void registerOptionDouble(std::string tab,std::string desc,std::string key,double min,double max,double defaultval); - double getOptionDouble(std::string key); - void setOptionDouble(std::string key,double val); - void registerOptionString(std::string tab,std::string desc,std::string key,std::string defaultval,bool ispath); - std::string getOptionString(std::string key); - void setOptionString(std::string key,std::string val); - void registerOptionEnumInt(std::string tab,std::string desc,std::string key,std::vector options,int defaultval); - int getOptionEnumInt(std::string key); - void setOptionEnumInt(std::string key,int val); void postInit(); + void registerCustomizeWidgetOptions(); + void registerSoundFontOption(); + void registerPluginOption(qmpPluginManager *pmgr); + void registerExtraMidiOptions(); signals: void dialogClosing(); @@ -118,36 +97,18 @@ class qmpSettingsWindow:public QDialog void on_buttonBox_accepted(); void on_buttonBox_rejected(); - void on_cbBufSize_currentTextChanged(const QString &s); - void on_cbBufCnt_currentTextChanged(const QString &s); - - void on_pbAdd_clicked(); - void on_pbRemove_clicked(); - void on_pbUp_clicked(); - void on_pbDown_clicked(); - - void on_cbAutoBS_stateChanged(); - - void on_pbCustomizeTb_clicked(); - - void on_pbCustomizeAct_clicked(); - - void on_pbExtDevSetup_clicked(); - - void on_pbDevPrio_clicked(); - private: Ui::qmpSettingsWindow *ui; - void settingsUpdate(); - std::map customOptions; + std::map customOptions; std::map customOptPages; - void updateCustomOptions(); - qmpCustomizeWindow *cw; + void saveOption(std::string key=std::string()); + void loadOption(std::string key=std::string()); + void setupWidgets(); + QGridLayout* pageForTab(std::string tab); + qmpCustomizeWindow *cwt,*cwa; qmpDevPropDialog *dps; qmpDevicePriorityDialog *devpriod; - static QSettings *settings; - public: - static QSettings* getSettingsIntf(){return settings;} + qmpSettings *settings; }; #endif // QMPSETTINGSWINDOW_H diff --git a/qmidiplayer-desktop/qmpsettingswindow.ui b/qmidiplayer-desktop/qmpsettingswindow.ui index 6cdd665..addf886 100644 --- a/qmidiplayer-desktop/qmpsettingswindow.ui +++ b/qmidiplayer-desktop/qmpsettingswindow.ui @@ -23,743 +23,8 @@ - 0 + -1 - - - Midi - - - - - - - 0 - 0 - - - - Disable Midi Mapping - - - - - - - - 0 - 0 - - - - Send SysEx - - - - - - - - 0 - 0 - - - - Wait for remaining voices before stopping - - - - - - - - - - 0 - 0 - - - - Text Encoding - - - - - - - - 0 - 0 - - - - - Unicode - - - - - Big5 - - - - - Big5-HKSCS - - - - - CP949 - - - - - EUC-JP - - - - - EUC-KR - - - - - GB18030 - - - - - KOI8-R - - - - - KOI8-U - - - - - Macintosh - - - - - Shift-JIS - - - - - - - - - - - - - 0 - 0 - - - - Select MIDI output devices - - - - - - - - 0 - 0 - - - - ... - - - - - - - - - - - - 0 - 0 - - - - External MIDI output device setup - - - - - - - - 0 - 0 - - - - ... - - - - - - - - - - Synth - - - - - - Audio Buffer Count - - - - - - - Audio Buffer Size - - - - - - - true - - - 1 - - - - 64 - - - - - 128 - - - - - 256 - - - - - 512 - - - - - 1024 - - - - - 2048 - - - - - 4096 - - - - - 8192 - - - - - - - - Sample Rate - - - - - - - true - - - - 2 - - - - - 4 - - - - - 8 - - - - - 16 - - - - - 32 - - - - - 64 - - - - - - - - Audio Driver - - - - - - - - 16bits - - - - - float - - - - - - - - - - - 2 - - - - 22050 - - - - - 44100 - - - - - 48000 - - - - - 96000 - - - - - - - - Sample Format - - - - - - - 1 - - - 65535 - - - 2048 - - - - - - - Max Polyphony - - - - - - - Auto bank select mode - - - - - - - Bank select mode - - - - - - - 1 - - - - Ignored - - - - - CC#0 - - - - - CC#32 - - - - - CC#0*128+CC#32 - - - - - - - - CPU Cores - - - - - - - 1 - - - 256 - - - - - - - - Soundfonts - - - - - - QAbstractItemView::InternalMove - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - - E - - - - - Path - - - - - - - - - - - - - - :/img/add.svg:/img/add.svg - - - - 24 - 24 - - - - - - - - - - - - :/img/remove.svg:/img/remove.svg - - - - 24 - 24 - - - - - - - - - - - - :/img/up.svg:/img/up.svg - - - - 24 - 24 - - - - - - - - - - - - :/img/down.svg:/img/down.svg - - - - 24 - 24 - - - - - - - - - - - Behavior - - - - - - - 0 - 0 - - - - Restore last playlist on startup - - - - - - - - 0 - 0 - - - - Load files in the same folder - - - - - - - - 0 - 0 - - - - Save dialog status - - - - - - - - 0 - 0 - - - - Save parameters in effects window - - - - - - - - 0 - 0 - - - - Persistent fluidsynth instance - - - - - - - - 0 - 0 - - - - Show label beside icon in toolbar buttons - - - - - - - - - - 0 - 0 - - - - Icon Theme - - - - - - - - Auto - - - - - Dark - - - - - Light - - - - - - - - - - - - Customize toolbar - - - - - - - Customize - - - - - - - - - - - Customize actions - - - - - - - Customize - - - - - - - - - - Plugins - - - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - - E - - - - - Name - - - - - Version - - - - - Path - - - - - - @@ -774,9 +39,7 @@ - - - + buttonBox diff --git a/qmidiplayer-desktop/translations/qmp_zh_CN.ts b/qmidiplayer-desktop/translations/qmp_zh_CN.ts index 233129e..4721a3a 100644 --- a/qmidiplayer-desktop/translations/qmp_zh_CN.ts +++ b/qmidiplayer-desktop/translations/qmp_zh_CN.ts @@ -4,7 +4,7 @@ QFileEdit - + Select a file 选择文件 @@ -12,27 +12,27 @@ main - + A cross-platform MIDI player. - + midi files to play (optional). - + Load a plugin from <plugin library>. - + Load all files from the same folder. - + Keep console window open. @@ -288,7 +288,7 @@ 取消全部独奏 - + Channel @@ -348,6 +348,22 @@ - + + + Select Device Initialization File + + + + + + Disconnected + + + + + Connected + + qmpDevicePriorityDialog @@ -572,27 +588,27 @@ 输出到wav文件 - + Render to wave 输出wav文件 - + Panic 关闭所有音符 - + Restart fluidsynth 重新载入FluidSynth - + Error 错误 - + %1 is not a valid midi file. %1是无效的midi文件。 @@ -601,7 +617,7 @@ qmpPlistWindow - + Playlist 播放列表 @@ -617,15 +633,15 @@ - - + + Repeat Off 循环关 - - + + Shuffle Off 随机关 @@ -650,30 +666,30 @@ 清空 - - + + Repeat One 循环当前 - - + + Repeat All 循环全部 - - + + Shuffle On 随机开 - + Save playlist 保存播放列表 - + Load playlist 加载播放列表 @@ -727,279 +743,99 @@ 选项 - Midi - MIDI选项 + MIDI选项 Default Output Device 默认输出设备 - Disable Midi Mapping - 只使用默认输出设备 + 只使用默认输出设备 - Send SysEx - 发送SysEx指令 + 发送SysEx指令 - Wait for remaining voices before stopping - 停止前等待复音数降为0 + 停止前等待复音数降为0 - Text Encoding - 文本编码 - - - - Unicode - + 文本编码 - - Big5 - - - - - Big5-HKSCS - - - - - CP949 - - - - - EUC-JP - - - - - EUC-KR - - - - - GB18030 - - - - - KOI8-R - - - - - KOI8-U - - - - - Macintosh - - - - - Shift-JIS - - - - Select MIDI output devices - 选择MIDI输出设备 + 选择MIDI输出设备 - - - ... - - - - External MIDI output device setup - 外部MIDI设备设置 + 外部MIDI设备设置 - Synth - 合成器 + 合成器 - Audio Buffer Count - 音频缓冲区数量 + 音频缓冲区数量 - Audio Buffer Size - 音频缓冲区大小 - - - - - 64 - - - - - 128 - + 音频缓冲区大小 - - 256 - - - - - 512 - - - - - 1024 - - - - - 2048 - - - - - 4096 - - - - - 8192 - - - - Sample Rate - 采样率 - - - - 2 - - - - - 4 - - - - - 8 - - - - - 16 - - - - - 32 - - - - - 16bits - - - - - float - - - - - 22050 - - - - - 44100 - - - - - 48000 - - - - - 96000 - + 采样率 - Sample Format - 采样格式 + 采样格式 - Show label beside icon in toolbar buttons - 工具栏按钮中显示文字标签 + 工具栏按钮中显示文字标签 - Icon Theme - 图标主题 + 图标主题 - Auto - 自动 + 自动 - Dark - 暗色 + 暗色 - Light - 亮色 + 亮色 - Customize toolbar - 自定义工具栏 + 自定义工具栏 - - Customize - 设置 + 设置 - Customize actions - 自定义右键菜单 + 自定义右键菜单 - Plugins - 插件 + 插件 - Name - 名称 + 名称 - + Version 版本 @@ -1008,110 +844,89 @@ 采样频率 - Audio Driver - 音频驱动 + 音频驱动 Audio Format 音频格式 - Max Polyphony - 最大复音数 + 最大复音数 - Auto bank select mode - 自动确定乐器库选择方式 + 自动确定乐器库选择方式 - Bank select mode - 乐器库选择方式 - - - - Ignored - + 乐器库选择方式 - - CC#0 - - - - - CC#32 - - - - - CC#0*128+CC#32 - - - - CPU Cores - 合成器线程数 + 合成器线程数 - Soundfonts - 音源 + 音源 - - + + E 启用 - - + + Path 路径 - Behavior - 行为设定 + 行为设定 - Restore last playlist on startup - 启动时,恢复上次的播放列表 + 启动时,恢复上次的播放列表 - Load files in the same folder - 添加同一文件夹下的所有文件 + 添加同一文件夹下的所有文件 - Save dialog status - 保存对话框状态 + 保存对话框状态 - Save parameters in effects window - 保存效果窗口内的设定 + 保存效果窗口内的设定 - Persistent fluidsynth instance - 单一fluidsynth实例 + 单一fluidsynth实例 - + No soundfont loaded 未选择soundfont - + Internal fluidsynth is the only available MIDI output but it has no soundfont set. Would you like to setup soundfonts now? You may have to reload the internal synth afterwards. 仅有FluidSynth输出可用,但未选择其使用的soundfont。需要现在进行设置吗?(设置完毕后需要重新加载FluidSynth。) + + + + Customize... + + + + + Plugin Name + + -- cgit v1.2.3