From d985112164bd2bfeca0c895abb523d45f0e065bb Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Wed, 18 Oct 2017 11:40:51 +0800 Subject: API changes and crash fixes. Details in the changelog. --- qmidiplayer-desktop/main.cpp | 2 + qmidiplayer-desktop/qmpchannelswindow.hpp | 2 +- qmidiplayer-desktop/qmpmainwindow.cpp | 84 ++++++++++++++++++++----------- qmidiplayer-desktop/qmpmainwindow.hpp | 34 ++++++++++--- qmidiplayer-desktop/qmpplugin.cpp | 18 ++++--- qmidiplayer-desktop/qmpsettingswindow.cpp | 6 +-- 6 files changed, 99 insertions(+), 47 deletions(-) (limited to 'qmidiplayer-desktop') diff --git a/qmidiplayer-desktop/main.cpp b/qmidiplayer-desktop/main.cpp index 2ac275e..c7167d0 100644 --- a/qmidiplayer-desktop/main.cpp +++ b/qmidiplayer-desktop/main.cpp @@ -23,6 +23,8 @@ int main(int argc,char **argv) { + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication a(argc,argv); QTranslator qtTranslator; qtTranslator.load("qt_"+QLocale::system().name(), diff --git a/qmidiplayer-desktop/qmpchannelswindow.hpp b/qmidiplayer-desktop/qmpchannelswindow.hpp index c7630fe..008598c 100644 --- a/qmidiplayer-desktop/qmpchannelswindow.hpp +++ b/qmidiplayer-desktop/qmpchannelswindow.hpp @@ -59,7 +59,7 @@ class QDCComboBox:public QComboBox void indexChangedSlot(int idx){emit(onChange(id,idx));} }; -class qmpCWNoteOnCB:public QObject,public IMidiCallBack +class qmpCWNoteOnCB:public QObject,public ICallBack { Q_OBJECT public: diff --git a/qmidiplayer-desktop/qmpmainwindow.cpp b/qmidiplayer-desktop/qmpmainwindow.cpp index b6e1267..dbec402 100644 --- a/qmidiplayer-desktop/qmpmainwindow.cpp +++ b/qmidiplayer-desktop/qmpmainwindow.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -22,19 +23,6 @@ char* wcsto8bit(const wchar_t* s) WideCharToMultiByte(CP_OEMCP,WC_NO_BEST_FIT_CHARS,s,-1,c,size,0,0); return c; } -#define LOAD_FILE \ - {\ - for(auto i=mfunc.begin();i!=mfunc.end();++i)if(i->second.isVisualization())((qmpVisualizationIntf*)(i->second.i()))->reset();\ - char* c=wcsto8bit(fns.toStdWString().c_str());\ - if(!player->playerLoadFile(c)){free(c);QMessageBox::critical(this,tr("Error"),tr("%1 is not a valid midi file.").arg(fns));return;}\ - free(c);\ - } -#else -#define LOAD_FILE \ - {\ - for(auto i=mfunc.begin();i!=mfunc.end();++i)if(i->second.isVisualization())((qmpVisualizationIntf*)(i->second.i()))->reset();\ - if(!player->playerLoadFile(fns.toStdString().c_str())){QMessageBox::critical(this,tr("Error"),tr("%1 is not a valid midi file.").arg(fns));return;}\ - } #endif #define UPDATE_INTERVAL 66 @@ -240,7 +228,7 @@ void qmpMainWindow::updateWidgets() if(!plistw->getRepeat()) { timer->stop();stopped=true;playing=false; - for(auto i=mfunc.begin();i!=mfunc.end();++i)if(i->second.isVisualization())((qmpVisualizationIntf*)(i->second.i()))->stop(); + invokeCallback("main.stop",NULL); setFuncEnabled("Render",stopped);setFuncEnabled("ReloadSynth",stopped); chnlw->resetAcitivity(); player->playerDeinit();playerTh->join(); @@ -288,7 +276,7 @@ void qmpMainWindow::switchTrack(QString s) setFuncEnabled("Render",stopped);setFuncEnabled("ReloadSynth",stopped); ui->pbPlayPause->setIcon(QIcon(getThemedIcon(":/img/pause.svg"))); timer->stop();player->playerDeinit(); - for(auto i=mfunc.begin();i!=mfunc.end();++i)if(i->second.isVisualization())((qmpVisualizationIntf*)(i->second.i()))->stop(); + invokeCallback("main.stop",NULL); if(playerTh){playerTh->join();delete playerTh;playerTh=NULL;} player->playerPanic(true); ui->hsTimer->setValue(0); @@ -296,12 +284,12 @@ void qmpMainWindow::switchTrack(QString s) QString fns=s;setWindowTitle(QUrl::fromLocalFile(fns).fileName().left(QUrl::fromLocalFile(fns).fileName().lastIndexOf('.'))+" - QMidiPlayer"); ui->lbFileName->setText(QUrl::fromLocalFile(fns).fileName().left(QUrl::fromLocalFile(fns).fileName().lastIndexOf('.'))); onfnChanged(); - LOAD_FILE; + if(!loadFile(fns))return; char ts[100]; sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); ui->lbFinTime->setText(ts); player->playerInit(); - for(auto i=mfunc.begin();i!=mfunc.end();++i)if(i->second.isVisualization())((qmpVisualizationIntf*)(i->second.i()))->start(); + invokeCallback("main.start",NULL); player->fluid()->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); playerTh=new std::thread(&CMidiPlayer::playerThread,player); @@ -379,6 +367,23 @@ void qmpMainWindow::loadSoundFont(IFluidSettings *fs) #endif } } +int qmpMainWindow::loadFile(QString fns) +{ +#ifdef _WIN32 + char* c=wcsto8bit(fns.toStdWString().c_str()); +#else + std::string s=fns.toStdString(); + const char* c=s.c_str(); +#endif + int ret=1; + invokeCallback("main.reset",NULL); + if(!player->playerLoadFile(c)) + {QMessageBox::critical(this,tr("Error"),tr("%1 is not a valid midi file.").arg(fns));ret=0;} +#ifdef _WIN32 + free(c); +#endif + return ret; +} void qmpMainWindow::on_pbPlayPause_clicked() { @@ -394,12 +399,12 @@ void qmpMainWindow::on_pbPlayPause_clicked() }setWindowTitle(QUrl::fromLocalFile(fns).fileName().left(QUrl::fromLocalFile(fns).fileName().lastIndexOf('.'))+" - QMidiPlayer"); ui->lbFileName->setText(QUrl::fromLocalFile(fns).fileName().left(QUrl::fromLocalFile(fns).fileName().lastIndexOf('.'))); onfnChanged(); - LOAD_FILE; + if(!loadFile(fns))return; char ts[100]; sprintf(ts,"%02d:%02d",(int)player->getFtime()/60,(int)player->getFtime()%60); ui->lbFinTime->setText(ts); player->playerInit(); - for(auto i=mfunc.begin();i!=mfunc.end();++i)if(i->second.isVisualization())((qmpVisualizationIntf*)(i->second.i()))->start(); + invokeCallback("main.start",NULL); player->fluid()->setGain(ui->vsMasterVol->value()/250.);efxw->sendEfxChange(); player->setWaitVoice(qmpSettingsWindow::getSettingsIntf()->value("Midi/WaitVoice",1).toInt()); playerTh=new std::thread(&CMidiPlayer::playerThread,player); @@ -423,7 +428,7 @@ void qmpMainWindow::on_pbPlayPause_clicked() player->setResumed(); } player->setTCpaused(!playing); - for(auto i=mfunc.begin();i!=mfunc.end();++i)if(i->second.isVisualization())((qmpVisualizationIntf*)(i->second.i()))->pause(); + invokeCallback("main.pause",NULL); } ui->pbPlayPause->setIcon(QIcon(getThemedIcon(playing?":/img/pause.svg":":/img/play.svg"))); } @@ -490,7 +495,7 @@ void qmpMainWindow::on_pbStop_clicked() if(!stopped) { timer->stop();stopped=true;playing=false; - for(auto i=mfunc.begin();i!=mfunc.end();++i)if(i->second.isVisualization())((qmpVisualizationIntf*)(i->second.i()))->stop(); + invokeCallback("main.stop",NULL); player->playerDeinit(); setFuncEnabled("Render",stopped);setFuncEnabled("ReloadSynth",stopped); player->playerPanic(true);chnlw->resetAcitivity(); @@ -543,19 +548,32 @@ void qmpMainWindow::onfnChanged() ui->lbFileName->setFont(f); } -void qmpMainWindow::registerVisualizationIntf(qmpVisualizationIntf* intf,std::string name,std::string desc,const char* icon,int iconlen) +int qmpMainWindow::registerUIHook(std::string e,ICallBack *callback,void* userdat) +{ + std::map>& m=muicb[e]; + int id=0; + if(m.size())id=m.rbegin()->first+1; + m[id]=std::make_pair(qmpCallBack(callback),userdat); + return id; +} +int qmpMainWindow::registerUIHook(std::string e,callback_t callback,void *userdat) { - registerFunctionality(intf,name,desc,icon,iconlen,true,true); + std::map>& m=muicb[e]; + int id=0; + if(m.size())id=m.rbegin()->first+1; + m[id]=std::make_pair(qmpCallBack(callback),userdat); + return id; } -void qmpMainWindow::unregisterVisualizationIntf(std::string name) +void qmpMainWindow::unregisterUIHook(std::string e,int hook) { - unregisterFunctionality(name); + std::map>& m=muicb[e]; + m.erase(hook); } -void qmpMainWindow::registerFunctionality(qmpFuncBaseIntf *i,std::string name,std::string desc,const char *icon,int iconlen,bool checkable,bool isv) +void qmpMainWindow::registerFunctionality(qmpFuncBaseIntf *i,std::string name,std::string desc,const char *icon,int iconlen,bool checkable) { if(mfunc.find(name)!=mfunc.end())return; - mfunc[name]=qmpFuncPrivate(i,desc,icon,iconlen,checkable,isv); + mfunc[name]=qmpFuncPrivate(i,desc,icon,iconlen,checkable); } void qmpMainWindow::unregisterFunctionality(std::string name) @@ -676,6 +694,14 @@ void qmpMainWindow::setupWidget() ui->buttonwidget->layout()->setAlignment(Qt::AlignLeft); } +void qmpMainWindow::invokeCallback(std::string cat,void* callerdat) +{ + std::map> *mp; + mp=&muicb[cat]; + for(auto&i:*mp) + i.second.first(callerdat,i.second.second); +} + void qmpMainWindow::on_pbSettings_clicked() { if(ui->pbSettings->isChecked())settingsw->show();else settingsw->close(); @@ -699,8 +725,8 @@ void qmpMainWindow::on_pushButton_clicked() helpw->show(); } -qmpFuncPrivate::qmpFuncPrivate(qmpFuncBaseIntf *i,std::string _desc,const char *icon,int iconlen,bool checkable,bool _isv): - _i(i),des(_desc),_checkable(checkable),visual(_isv) +qmpFuncPrivate::qmpFuncPrivate(qmpFuncBaseIntf *i,std::string _desc,const char *icon,int iconlen,bool checkable): + _i(i),des(_desc),_checkable(checkable) { if(icon) { diff --git a/qmidiplayer-desktop/qmpmainwindow.hpp b/qmidiplayer-desktop/qmpmainwindow.hpp index c713ca3..a70083a 100644 --- a/qmidiplayer-desktop/qmpmainwindow.hpp +++ b/qmidiplayer-desktop/qmpmainwindow.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "../core/qmpmidiplay.hpp" #include "qmpplugin.hpp" #include "qmpplistwindow.hpp" @@ -95,19 +96,18 @@ class qmpFuncPrivate qmpFuncBaseIntf* _i; QIcon _icon; std::string des; - bool _checkable,checked,visual; + bool _checkable,checked; QReflectiveAction* asgna; QReflectivePushButton* asgnb; public: qmpFuncPrivate(){} - qmpFuncPrivate(qmpFuncBaseIntf* i,std::string _desc,const char* icon,int iconlen,bool checkable,bool _isv); + qmpFuncPrivate(qmpFuncBaseIntf* i,std::string _desc,const char* icon,int iconlen,bool checkable); ~qmpFuncPrivate(){asgna=NULL;asgnb=NULL;} qmpFuncBaseIntf* i(){return _i;} void setAssignedControl(QReflectiveAction* a){asgna=a;if(!a)return;asgna->setCheckable(_checkable);asgna->setChecked(checked);} void setAssignedControl(QReflectivePushButton* a){asgnb=a;if(!a)return;asgnb->setCheckable(_checkable);asgnb->setChecked(checked);} const QIcon& icon(){return _icon;} const std::string& desc(){return des;} - bool isVisualization(){return visual;} bool isCheckable(){return _checkable;} bool isChecked(){return checked;} void setEnabled(bool e){if(asgna)asgna->setEnabled(e);if(asgnb)asgnb->setEnabled(e);} @@ -118,6 +118,24 @@ class qmpRenderFunc; class qmpPanicFunc; class qmpReloadSynthFunc; +class qmpCallBack +{ + private: + int t; + ICallBack* cbc; + callback_t cbf; + public: + qmpCallBack(){t=-1;cbc=NULL;cbf=NULL;} + qmpCallBack(ICallBack* _cb){t=0;cbc=_cb;cbf=NULL;} + qmpCallBack(callback_t _cb){t=1;cbf=_cb;cbc=NULL;} + void operator ()(void* cbd,void* usrd) + { + if(t<0)return; + if(t)cbf(cbd,usrd); + else cbc->callBack(cbd,usrd); + } +}; + class qmpMainWindow:public QMainWindow { Q_OBJECT @@ -140,16 +158,18 @@ class qmpMainWindow:public QMainWindow uint32_t getPlaybackPercentage(); void playerSeek(uint32_t percentage); int pharseArgs(); - void registerVisualizationIntf(qmpVisualizationIntf* intf,std::string name,std::string desc,const char* icon,int iconlen); - void unregisterVisualizationIntf(std::string name); - void registerFunctionality(qmpFuncBaseIntf* i,std::string name,std::string desc,const char* icon,int iconlen,bool checkable,bool isv=false); + void registerFunctionality(qmpFuncBaseIntf* i,std::string name,std::string desc,const char* icon,int iconlen,bool checkable); void unregisterFunctionality(std::string name); + int registerUIHook(std::string e,ICallBack* callback,void* userdat); + int registerUIHook(std::string e,callback_t callback,void* userdat); + void unregisterUIHook(std::string e,int hook); void setFuncState(std::string name,bool state); void setFuncEnabled(std::string name,bool enable); bool isDarkTheme(); void startRender(); void reloadSynth(); void setupWidget(); + void invokeCallback(std::string cat,void *callerdat); std::vector& getWidgets(int w); std::map& getFunc(); @@ -191,6 +211,7 @@ class qmpMainWindow:public QMainWindow QPointer settingsw; QPointer helpw; std::map mfunc; + std::unordered_map>> muicb; qmpRenderFunc* renderf; qmpPanicFunc* panicf; qmpReloadSynthFunc* reloadsynf; @@ -199,6 +220,7 @@ class qmpMainWindow:public QMainWindow void onfnChanged(); void playerSetup(IFluidSettings *fs); void loadSoundFont(IFluidSettings *fs); + int loadFile(QString fns); private: static qmpMainWindow* ref; diff --git a/qmidiplayer-desktop/qmpplugin.cpp b/qmidiplayer-desktop/qmpplugin.cpp index 6eca257..4c0ee7c 100644 --- a/qmidiplayer-desktop/qmpplugin.cpp +++ b/qmidiplayer-desktop/qmpplugin.cpp @@ -193,27 +193,29 @@ void qmpPluginAPI::registerMidiOutDevice(qmpMidiOutDevice *dev, std::string name {qmw->getPlayer()->registerMidiOutDevice(dev,name);} void qmpPluginAPI::unregisterMidiOutDevice(std::string name) {qmw->getPlayer()->unregisterMidiOutDevice(name);} -int qmpPluginAPI::registerEventHandlerIntf(IMidiCallBack *cb,void *userdata) +int qmpPluginAPI::registerEventHandlerIntf(ICallBack *cb,void *userdata) {return qmw->getPlayer()->setEventHandlerCB(cb,userdata);} void qmpPluginAPI::unregisterEventHandlerIntf(int intfhandle) {qmw->getPlayer()->unsetEventHandlerCB(intfhandle);} -int qmpPluginAPI::registerEventReaderIntf(IMidiCallBack *cb,void *userdata) +int qmpPluginAPI::registerEventReaderIntf(ICallBack *cb,void *userdata) {return qmw->getPlayer()->setEventReaderCB(cb,userdata);} void qmpPluginAPI::unregisterEventReaderIntf(int intfhandle) {qmw->getPlayer()->unsetEventReaderCB(intfhandle);} -void qmpPluginAPI::registerVisualizationIntf(qmpVisualizationIntf* intf,std::string name,std::string desc,const char* icon,int iconlen) -{qmw->registerVisualizationIntf(intf,name,desc,icon,iconlen);} -void qmpPluginAPI::unregisterVisualizationIntf(std::string name) -{qmw->unregisterVisualizationIntf(name);} +int qmpPluginAPI::registerUIHook(std::string e,ICallBack* cb,void* userdat) +{return qmw->registerUIHook(e,cb,userdat);} +int qmpPluginAPI::registerUIHook(std::string e,callback_t cb,void* userdat) +{return qmw->registerUIHook(e,cb,userdat);} +void qmpPluginAPI::unregisterUIHook(std::string e,int hook) +{qmw->unregisterUIHook(e,hook);} void qmpPluginAPI::registerFunctionality(qmpFuncBaseIntf *i,std::string name,std::string desc,const char *icon,int iconlen,bool checkable) {qmw->registerFunctionality(i,name,desc,icon,iconlen,checkable);} void qmpPluginAPI::unregisterFunctionality(std::string name) {qmw->unregisterFunctionality(name);} -int qmpPluginAPI::registerFileReadFinishedHandlerIntf(IMidiCallBack* cb,void* userdata) +int qmpPluginAPI::registerFileReadFinishedHandlerIntf(ICallBack* cb,void* userdata) {return qmw->getPlayer()->setFileReadFinishedCB(cb,userdata);} void qmpPluginAPI::unregisterFileReadFinishedHandlerIntf(int intfhandle) {qmw->getPlayer()->unsetFileReadFinishedCB(intfhandle);} -void qmpPluginAPI::registerFileReader(IMidiFileReader* reader,std::string name) +void qmpPluginAPI::registerFileReader(qmpFileReader* reader,std::string name) {qmw->getPlayer()->registerReader(reader,name);} void qmpPluginAPI::unregisterFileReader(std::string name) {qmw->getPlayer()->unregisterReader(name);} diff --git a/qmidiplayer-desktop/qmpsettingswindow.cpp b/qmidiplayer-desktop/qmpsettingswindow.cpp index ba460dd..0f5b66a 100644 --- a/qmidiplayer-desktop/qmpsettingswindow.cpp +++ b/qmidiplayer-desktop/qmpsettingswindow.cpp @@ -383,9 +383,9 @@ void qmpSettingsWindow::verifySF() if(((QCheckBox*)ui->twSoundfont->cellWidget(i,0))->isChecked())++sf; if(settings->value("Midi/DefaultOutput","Internal FluidSynth").toString()=="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, + // 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. " "Would you like to setup soundfonts now? After that you may have to reload the internal synth."))==QMessageBox::Yes) -- cgit v1.2.3