From 8cf35c5ceb10d5c54e933127fb60c5034ef8a149 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Sat, 5 Oct 2019 23:04:53 +0800 Subject: Replaced the option "default output device" with a more powerful one. Old code for default output device completely removed. --- ChangeLog | 3 + core/qmpmidioutrtmidi.cpp | 17 ++--- core/qmpmidioutrtmidi.hpp | 7 +- qmidiplayer-desktop/CMakeLists.txt | 3 + qmidiplayer-desktop/qmpchannelswindow.cpp | 25 +++---- qmidiplayer-desktop/qmpdeviceprioritydialog.cpp | 98 +++++++++++++++++++++++++ qmidiplayer-desktop/qmpdeviceprioritydialog.hpp | 32 ++++++++ qmidiplayer-desktop/qmpdeviceprioritydialog.ui | 85 +++++++++++++++++++++ qmidiplayer-desktop/qmphelpwindow.hpp | 2 +- qmidiplayer-desktop/qmpmainwindow.cpp | 9 +-- qmidiplayer-desktop/qmpmainwindow.hpp | 1 - qmidiplayer-desktop/qmpsettingswindow.cpp | 33 ++++++--- qmidiplayer-desktop/qmpsettingswindow.hpp | 9 ++- qmidiplayer-desktop/qmpsettingswindow.ui | 63 ++++++++-------- 14 files changed, 305 insertions(+), 82 deletions(-) create mode 100644 qmidiplayer-desktop/qmpdeviceprioritydialog.cpp create mode 100644 qmidiplayer-desktop/qmpdeviceprioritydialog.hpp create mode 100644 qmidiplayer-desktop/qmpdeviceprioritydialog.ui diff --git a/ChangeLog b/ChangeLog index 842fa4d..e0c143c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +== This file will no longer be updated since October 2019. == +As we are now just pasting commit messages into this file. + 2019-09-25 0.8.7 indev Use QStandardPaths. diff --git a/core/qmpmidioutrtmidi.cpp b/core/qmpmidioutrtmidi.cpp index c37fadc..fba8e03 100644 --- a/core/qmpmidioutrtmidi.cpp +++ b/core/qmpmidioutrtmidi.cpp @@ -312,26 +312,19 @@ void qmpMidiOutRtMidi::setInitializerFile(const char* path) devinit=qmpDeviceInitializer::parse(path); } -RtMidiOut* qmpRtMidiManager::dummy=nullptr; -void qmpRtMidiManager::createDevices() +std::vector> qmpRtMidiManager::devices; +std::vector> qmpRtMidiManager::getDevices() { + if(devices.size())return devices; + RtMidiOut *dummy; try{dummy=new RtMidiOut();} catch(RtMidiError &e) { printf("Failed to initialize the dummy device: %s\n",e.what()); - dummy=nullptr;return; + return{}; } for(unsigned i=0;igetPortCount();++i) devices.push_back(std::make_pair(new qmpMidiOutRtMidi(i),dummy->getPortName(i))); -} -void qmpRtMidiManager::deleteDevices() -{ - for(size_t i=0;i> qmpRtMidiManager::getDevices() -{ return devices; } diff --git a/core/qmpmidioutrtmidi.hpp b/core/qmpmidioutrtmidi.hpp index 0a4fd60..ee9a7d2 100644 --- a/core/qmpmidioutrtmidi.hpp +++ b/core/qmpmidioutrtmidi.hpp @@ -48,11 +48,8 @@ public: class qmpRtMidiManager { private: - static RtMidiOut* dummy; - std::vector> devices; + static std::vector> devices; public: - void createDevices(); - void deleteDevices(); - std::vector> getDevices(); + static std::vector> getDevices(); }; #endif // QMPMIDIMAPPERS_H diff --git a/qmidiplayer-desktop/CMakeLists.txt b/qmidiplayer-desktop/CMakeLists.txt index 1f40a2e..9b488e2 100644 --- a/qmidiplayer-desktop/CMakeLists.txt +++ b/qmidiplayer-desktop/CMakeLists.txt @@ -3,6 +3,7 @@ set(qmpdesktop_SOURCES qmpchanneleditor.hpp qmpchannelswindow.hpp qmpcustomizewindow.hpp + qmpdeviceprioritydialog.hpp qmpdevpropdialog.hpp qmpefxwindow.hpp qmphelpwindow.hpp @@ -17,6 +18,7 @@ set(qmpdesktop_SOURCES qmpchanneleditor.cpp qmpchannelswindow.cpp qmpcustomizewindow.cpp + qmpdeviceprioritydialog.cpp qmpdevpropdialog.cpp qmpefxwindow.cpp qmphelpwindow.cpp @@ -29,6 +31,7 @@ set(qmpdesktop_SOURCES qmpchanneleditor.ui qmpchannelswindow.ui qmpcustomizewindow.ui + qmpdeviceprioritydialog.ui qmpdevpropdialog.ui qmpefxwindow.ui qmphelpwindow.ui diff --git a/qmidiplayer-desktop/qmpchannelswindow.cpp b/qmidiplayer-desktop/qmpchannelswindow.cpp index 0c34239..029daff 100644 --- a/qmidiplayer-desktop/qmpchannelswindow.cpp +++ b/qmidiplayer-desktop/qmpchannelswindow.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -256,27 +257,23 @@ qmpChannelsWindow::qmpChannelsWindow(QWidget *parent) : ,nullptr); std::vector devs=qmpMainWindow::getInstance()->getPlayer()->getMidiOutDevices(); size_t devc=devs.size(); - //We setup default output here... - //Pretty strange... - for(size_t i=0;iaddItem(devs[i].c_str()); - if(!QString(devs[i].c_str()).compare(qmpSettingsWindow::getSettingsIntf()-> - value("Midi/DefaultOutput","Internal FluidSynth").toString())) - qmpSettingsWindow::getDefaultOutWidget()->setCurrentIndex(i); - } + 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;j - value("Midi/DefaultOutput","Internal FluidSynth").toString().compare( - QString(devs[j].c_str()))) + if(selecteddev==devs[j]) qmpMainWindow::getInstance()->getPlayer()->setChannelOutput(ch,j); } } - qmpSettingsWindow::getSettingsIntf()->setValue("Midi/DefaultOutput", - qmpSettingsWindow::getDefaultOutWidget()->currentText()); qmpMainWindow::getInstance()->registerFunctionality( chnlf=new qmpChannelFunc(this), std::string("Channel"), diff --git a/qmidiplayer-desktop/qmpdeviceprioritydialog.cpp b/qmidiplayer-desktop/qmpdeviceprioritydialog.cpp new file mode 100644 index 0000000..a319fd1 --- /dev/null +++ b/qmidiplayer-desktop/qmpdeviceprioritydialog.cpp @@ -0,0 +1,98 @@ +#include +#include +#include "qmpdeviceprioritydialog.hpp" +#include "qmpsettingswindow.hpp" +#include "../core/qmpmidiplay.hpp" +#include "ui_qmpdeviceprioritydialog.h" + +qmpDevicePriorityDialog::qmpDevicePriorityDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::qmpDevicePriorityDialog) +{ + ui->setupUi(this); + model=new QStandardItemModel(this); + ui->tvDevices->setModel(model); + ui->tvDevices->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); + 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() +{ + delete ui; +} + +void qmpDevicePriorityDialog::setupRegisteredDevices() +{ + std::set sset,sconn; + auto conndevs=CMidiPlayer::getInstance()->getMidiOutDevices(); + for(auto dev:conndevs) + sconn.insert(dev); + for(auto dev:setdevs) + { + QStandardItem *e=new QStandardItem; + e->setCheckable(true); + e->setEditable(false); + e->setCheckState(Qt::CheckState::Checked); + QStandardItem *a=new QStandardItem; + a->setEnabled(false); + a->setText(sconn.find(dev.toString().toStdString())!=sconn.end()?"Connected":"Disconnected"); + a->setEditable(false); + QStandardItem *devn=new QStandardItem(dev.toString()); + devn->setEditable(false); + model->appendRow({e,devn,a}); + sset.insert(dev.toString().toStdString()); + } + for(auto dev:conndevs) + { + if(sset.find(dev)!=sset.end())continue; + QStandardItem *e=new QStandardItem; + e->setCheckable(true); + e->setEditable(false); + e->setCheckState(Qt::CheckState::Unchecked); + QStandardItem *a=new QStandardItem; + a->setEnabled(false); + a->setText("Connected"); + a->setEditable(false); + QStandardItem *devn=new QStandardItem(QString::fromStdString(dev)); + devn->setEditable(false); + model->appendRow({e,devn,a}); + } +} + +void qmpDevicePriorityDialog::on_pbUp_clicked() +{ + const QModelIndex &idx=ui->tvDevices->selectionModel()->currentIndex(); + if(idx.isValid()&&idx.row()>0) + { + int row=idx.row(); + auto r=model->takeRow(row); + model->insertRow(row-1,r); + ui->tvDevices->clearSelection(); + ui->tvDevices->selectionModel()->setCurrentIndex(model->index(row-1,idx.column()),QItemSelectionModel::Rows|QItemSelectionModel::Select); + } +} + +void qmpDevicePriorityDialog::on_pbDown_clicked() +{ + const QModelIndex &idx=ui->tvDevices->selectionModel()->currentIndex(); + if(idx.isValid()&&idx.row()rowCount()-1) + { + int row=idx.row(); + auto r=model->takeRow(row); + model->insertRow(row+1,r); + ui->tvDevices->clearSelection(); + ui->tvDevices->selectionModel()->setCurrentIndex(model->index(row+1,idx.column()),QItemSelectionModel::Rows|QItemSelectionModel::Select); + } +} + +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); +} diff --git a/qmidiplayer-desktop/qmpdeviceprioritydialog.hpp b/qmidiplayer-desktop/qmpdeviceprioritydialog.hpp new file mode 100644 index 0000000..d48a2aa --- /dev/null +++ b/qmidiplayer-desktop/qmpdeviceprioritydialog.hpp @@ -0,0 +1,32 @@ +#ifndef QMPDEVICEPRIORITYDIALOG_HPP +#define QMPDEVICEPRIORITYDIALOG_HPP + +#include +#include +#include + +namespace Ui { +class qmpDevicePriorityDialog; +} + +class qmpDevicePriorityDialog : public QDialog +{ + Q_OBJECT + +public: + explicit qmpDevicePriorityDialog(QWidget *parent=nullptr); + ~qmpDevicePriorityDialog(); + void setupRegisteredDevices(); + +private slots: + void on_pbUp_clicked(); + void on_pbDown_clicked(); + void on_buttonBox_accepted(); + +private: + Ui::qmpDevicePriorityDialog *ui; + QStandardItemModel *model; + QList setdevs; +}; + +#endif // QMPDEVICEPRIORITYDIALOG_HPP diff --git a/qmidiplayer-desktop/qmpdeviceprioritydialog.ui b/qmidiplayer-desktop/qmpdeviceprioritydialog.ui new file mode 100644 index 0000000..9fc464f --- /dev/null +++ b/qmidiplayer-desktop/qmpdeviceprioritydialog.ui @@ -0,0 +1,85 @@ + + + qmpDevicePriorityDialog + + + + 0 + 0 + 400 + 300 + + + + Select MIDI Output Devices + + + + + + + + + + + Move Up + + + + + + + Move Down + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + qmpDevicePriorityDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + qmpDevicePriorityDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/qmidiplayer-desktop/qmphelpwindow.hpp b/qmidiplayer-desktop/qmphelpwindow.hpp index f68e38e..4e1ca4c 100644 --- a/qmidiplayer-desktop/qmphelpwindow.hpp +++ b/qmidiplayer-desktop/qmphelpwindow.hpp @@ -2,7 +2,7 @@ #define QMPHELPWINDOW_H #include -#define APP_VERSION "0.8.6" +#define APP_VERSION "0.8.7" #ifndef BUILD_MACHINE #define BUILD_MACHINE UNKNOWN #endif diff --git a/qmidiplayer-desktop/qmpmainwindow.cpp b/qmidiplayer-desktop/qmpmainwindow.cpp index 76cd221..0bcf070 100644 --- a/qmidiplayer-desktop/qmpmainwindow.cpp +++ b/qmidiplayer-desktop/qmpmainwindow.cpp @@ -52,9 +52,8 @@ qmpMainWindow::~qmpMainWindow() delete a[i]; } pmgr->deinitPlugins(); - std::vector> rtdev=rtmididev->getDevices(); + auto rtdev=qmpRtMidiManager::getDevices(); for(auto &i:rtdev)player->unregisterMidiOutDevice(i.second); - rtmididev->deleteDevices(); delete pmgr; if(timer)delete timer; delete helpw;helpw=nullptr; @@ -83,9 +82,7 @@ void qmpMainWindow::init() [this] { player=new CMidiPlayer(); - rtmididev=new qmpRtMidiManager(); - rtmididev->createDevices(); - std::vector> rtdev=rtmididev->getDevices(); + auto rtdev=qmpRtMidiManager::getDevices(); for(auto &i:rtdev) { player->registerMidiOutDevice(i.first,i.second); @@ -133,7 +130,7 @@ void qmpMainWindow::init() ui->pbSettings->setIcon(QIcon(getThemedIcon(":/img/settings.svg"))); ui->pbAdd->setIcon(QIcon(getThemedIcon(":/img/open.svg"))); if(argfiles.size())on_pbPlayPause_clicked(); - setupWidget();settingsw->verifySF(); + setupWidget();settingsw->postInit(); } int qmpMainWindow::parseArgs() diff --git a/qmidiplayer-desktop/qmpmainwindow.hpp b/qmidiplayer-desktop/qmpmainwindow.hpp index a95d1fe..ea5209c 100644 --- a/qmidiplayer-desktop/qmpmainwindow.hpp +++ b/qmidiplayer-desktop/qmpmainwindow.hpp @@ -194,7 +194,6 @@ class qmpMainWindow:public QMainWindow std::chrono::steady_clock::time_point st; double offset; CMidiPlayer *player; - qmpRtMidiManager *rtmididev; qmpFileRendererFluid *fluidrenderer; qmpPluginManager *pmgr; QPointer plistw; diff --git a/qmidiplayer-desktop/qmpsettingswindow.cpp b/qmidiplayer-desktop/qmpsettingswindow.cpp index bb0ba05..409b087 100644 --- a/qmidiplayer-desktop/qmpsettingswindow.cpp +++ b/qmidiplayer-desktop/qmpsettingswindow.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,11 +7,11 @@ #include #include #include "qmpsettingswindow.hpp" +#include "qmpdeviceprioritydialog.hpp" #include "ui_qmpsettingswindow.h" #include "qmpmainwindow.hpp" QSettings* qmpSettingsWindow::settings=nullptr; -QComboBox* qmpSettingsWindow::outwidget=nullptr; void qmpFluidForEachOpt(void* data,const char*,const char* option) { @@ -25,13 +26,14 @@ qmpSettingsWindow::qmpSettingsWindow(QWidget *parent) : 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();outwidget=ui->cbOutputDevice; + 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); dps=new qmpDevPropDialog(this); + devpriod=new qmpDevicePriorityDialog(this); } qmpSettingsWindow::~qmpSettingsWindow() @@ -56,7 +58,6 @@ void qmpSettingsWindow::hideEvent(QHideEvent *event) QTableWidget* qmpSettingsWindow::getSFWidget(){return ui->twSoundfont;} -QComboBox* qmpSettingsWindow::getDefaultOutWidget(){return outwidget;} void qmpSettingsWindow::on_buttonBox_accepted() { @@ -75,8 +76,6 @@ void qmpSettingsWindow::settingsInit() { fluid_settings_t *fsettings=new_fluid_settings(); - settings->setValue("Midi/DefaultOutput",settings->value("Midi/DefaultOutput","Internal FluidSynth")); - settings->setValue("Midi/DisableMapping",settings->value("Midi/DisableMapping",0)); ui->cbDisableMapping->setChecked(settings->value("Midi/DisableMapping",0).toInt()); @@ -208,8 +207,6 @@ void qmpSettingsWindow::settingsInit() void qmpSettingsWindow::settingsUpdate() { - settings->setValue("Midi/DefaultOutput",ui->cbOutputDevice->currentText()); - settings->setValue("Midi/DisableMapping",ui->cbDisableMapping->isChecked()?1:0); settings->setValue("Midi/SendSysEx",ui->cbSendSysx->isChecked()?1:0); @@ -376,24 +373,35 @@ void qmpSettingsWindow::updatePluginList(qmpPluginManager *pmgr) ui->twPluginList->setColumnWidth(3,128); } -void qmpSettingsWindow::verifySF() +void qmpSettingsWindow::postInit() { int sf=0; for(int i=0;itwSoundfont->rowCount();++i) if(((QCheckBox*)ui->twSoundfont->cellWidget(i,0))->isChecked())++sf; - if(settings->value("Midi/DefaultOutput","Internal FluidSynth").toString()=="Internal FluidSynth"&&!sf) + 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()) + if(devset.find(setdev.toString().toStdString())!=devset.end()) + { + selecteddev=setdev.toString().toStdString(); + break; + } + if(selecteddev=="Internal FluidSynth"&&!sf) { // blmark: show dialog at the current screen which user using now. int curMonitor = QApplication::desktop()->screenNumber(this); if(QMessageBox::question(QDesktopWidget().screen(curMonitor),//this, tr("No soundfont loaded"), - tr("Internal fluidsynth was chosen as the default output but it has no soundfont set. " + tr("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."))==QMessageBox::Yes) { show(); ui->tabWidget->setCurrentWidget(ui->tab_3); } } + devpriod->setupRegisteredDevices(); } void qmpSettingsWindow::updateCustomOptions() @@ -747,3 +755,8 @@ 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 72b0aa1..0e208ca 100644 --- a/qmidiplayer-desktop/qmpsettingswindow.hpp +++ b/qmidiplayer-desktop/qmpsettingswindow.hpp @@ -79,6 +79,8 @@ class QHexSpinBox:public QSpinBox {return *reinterpret_cast(&u);} }; +class qmpDevicePriorityDialog; + class qmpSettingsWindow:public QDialog { Q_OBJECT @@ -109,7 +111,7 @@ class qmpSettingsWindow:public QDialog 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 verifySF(); + void postInit(); signals: void dialogClosing(); @@ -133,6 +135,8 @@ class qmpSettingsWindow:public QDialog void on_pbExtDevSetup_clicked(); + void on_pbDevPrio_clicked(); + private: Ui::qmpSettingsWindow *ui; void settingsUpdate(); @@ -141,11 +145,10 @@ class qmpSettingsWindow:public QDialog void updateCustomOptions(); qmpCustomizeWindow *cw; qmpDevPropDialog *dps; + qmpDevicePriorityDialog *devpriod; static QSettings *settings; - static QComboBox* outwidget; public: static QSettings* getSettingsIntf(){return settings;} - static QComboBox* getDefaultOutWidget(); }; #endif // QMPSETTINGSWINDOW_H diff --git a/qmidiplayer-desktop/qmpsettingswindow.ui b/qmidiplayer-desktop/qmpsettingswindow.ui index a2400c5..3619943 100644 --- a/qmidiplayer-desktop/qmpsettingswindow.ui +++ b/qmidiplayer-desktop/qmpsettingswindow.ui @@ -30,37 +30,10 @@ Midi - - - - - - - 0 - 0 - - - - Default Output Device - - - - - - - - 0 - 0 - - - - - - - + 0 0 @@ -73,7 +46,7 @@ - + 0 0 @@ -86,7 +59,7 @@ - + 0 0 @@ -178,6 +151,36 @@ + + + + + + + 0 + 0 + + + + Select MIDI output devices + + + + + + + + 0 + 0 + + + + ... + + + + + -- cgit v1.2.3