From 795043d6851a355d70aa2341e2edfd526c24d041 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Sun, 16 Jun 2019 20:12:14 +0800 Subject: Inital implementation of the device properties API. Added new interfaces to qmpMidiOutDevice. Implemented the new interfaces for qmpMidiOutFluid. Initial infra for device initialization file parsing. Move to the new interfaces for getting list of presets. Use DevIL instead of CxImage. External output devices are broken now but that is for another commit. --- ChangeLog | 12 +++ core/qmpmidioutfluid.cpp | 76 ++++++++++++--- core/qmpmidioutfluid.hpp | 10 +- core/qmpmidioutrtmidi.cpp | 151 ++++++++++++++++++++++++++++++ core/qmpmidioutrtmidi.hpp | 19 ++++ core/qmpmidiplay.cpp | 19 +--- core/qmpmidiplay.hpp | 2 +- core/qmpmidiread.cpp | 11 ++- include/qmpcorepublic.hpp | 7 ++ qmidiplayer-desktop/qmpchanneleditor.cpp | 6 +- qmidiplayer-desktop/qmpchannelswindow.cpp | 9 +- qmidiplayer-desktop/qmpplugin.cpp | 13 +-- qmidiplayer-desktop/qmppresetselect.cpp | 52 +++++----- visualization/visualization.pro | 4 +- 14 files changed, 316 insertions(+), 75 deletions(-) diff --git a/ChangeLog b/ChangeLog index 65c5997..9c656ed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2019-06-16 0.8.7 indev +Inital implementation of the device properties API. + +Added new interfaces to qmpMidiOutDevice. +Implemented the new interfaces for qmpMidiOutFluid. +Initial infra for device initialization file parsing. +Move to the new interfaces for getting list of presets. +Use DevIL instead of CxImage. + +External output devices are broken now but that is for +another commit. + 2019-05-26 0.8.7 indev New flag field in SEvent. Further type usage corrections. diff --git a/core/qmpmidioutfluid.cpp b/core/qmpmidioutfluid.cpp index bb8f290..414cb3a 100644 --- a/core/qmpmidioutfluid.cpp +++ b/core/qmpmidioutfluid.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include "qmpmidioutfluid.hpp" qmpMidiOutFluid::qmpMidiOutFluid() { @@ -30,6 +30,7 @@ void qmpMidiOutFluid::deviceInit() } fluid_synth_set_chorus(synth,3,2.0,0.3,8.0, FLUID_CHORUS_MOD_SINE); + bnk.clear();pst.clear(); } void qmpMidiOutFluid::deviceDeinit(){deviceDeinit(false);} void qmpMidiOutFluid::deviceDeinit(bool freshsettings) @@ -38,6 +39,7 @@ void qmpMidiOutFluid::deviceDeinit(bool freshsettings) delete_fluid_audio_driver(adriver); delete_fluid_synth(synth); synth=nullptr;adriver=nullptr; + bnk.clear();pst.clear(); if(freshsettings) { delete_fluid_settings(settings); @@ -117,6 +119,54 @@ void qmpMidiOutFluid::onMapped(uint8_t,int) void qmpMidiOutFluid::onUnmapped(uint8_t,int) { } +std::vector> qmpMidiOutFluid::getBankList() +{ + return bnk; +} +std::vector> qmpMidiOutFluid::getPresets(int bank) +{ + std::vector> ret; + if(pst.find(bank)==pst.end())return ret; + for(uint8_t i=0;i<128;++i) + { + if(pst[bank][i].length()) + ret.emplace_back(i,pst[bank][i]); + } + return ret; +} +std::string qmpMidiOutFluid::getPresetName(uint16_t bank,uint8_t preset) +{ + if(pst.find(bank)==pst.end())return ""; + return pst[bank][preset]; +} +bool qmpMidiOutFluid::getChannelPreset(int ch,uint16_t *bank,uint8_t *preset,std::string &presetname) +{ + if(!synth)return false; + fluid_preset_t* chpreset=fluid_synth_get_channel_preset(synth,ch); + if(!chpreset) + { + *bank=*preset=-1; + presetname="---"; + return true; + } + *bank=fluid_preset_get_banknum(chpreset); + *preset=fluid_preset_get_num(chpreset); + presetname=fluid_preset_get_name(chpreset); + return true; +} +uint8_t qmpMidiOutFluid::getInitialCCValue(uint8_t cc) +{ + switch(cc) + { + case 11:return 127; + case 7:return 100; + case 8:case 10:case 71:case 72: + case 73:case 74:case 75:case 76: + case 77:case 78:return 64; + case 129:return 2; + default:return 0; + } +} void qmpMidiOutFluid::setOptStr(const char *opt,const char *val) { fluid_settings_setstr(settings,opt,val); @@ -132,29 +182,33 @@ void qmpMidiOutFluid::setOptNum(const char *opt,double val) void qmpMidiOutFluid::loadSFont(const char *path) { if(synth)fluid_synth_sfload(synth,path,1); + update_preset_list(); } int qmpMidiOutFluid::getSFCount() { return synth?fluid_synth_sfcount(synth):0; } -std::vector,std::string>> qmpMidiOutFluid::listPresets() +void qmpMidiOutFluid::update_preset_list() { - std::vector,std::string>> ret; - std::map,std::string> pmap; + bnk.clear();pst.clear(); for(int i=getSFCount()-1;i>=0;--i) { fluid_sfont_t* psf=fluid_synth_get_sfont(synth,i); fluid_preset_t* preset; fluid_sfont_iteration_start(psf); while(preset=fluid_sfont_iteration_next(psf)) - pmap[std::make_pair( - fluid_preset_get_banknum(preset), - fluid_preset_get_num(preset) - )]=fluid_preset_get_name(preset); + { + uint16_t b=fluid_preset_get_banknum(preset); + uint8_t p=fluid_preset_get_num(preset); + if(bnk.empty()||bnk.back().first!=b) + bnk.emplace_back(b,""); + if(pst[b].empty())pst[b].resize(128); + pst[b][p]=std::string(fluid_preset_get_name(preset)); + if(!pst[b][p].length())pst[b][p]=" "; + } } - for(auto i=pmap.begin();i!=pmap.end();++i) - ret.push_back(std::make_pair(i->first,i->second)); - return ret; + std::sort(bnk.begin(),bnk.end()); + bnk.erase(std::unique(bnk.begin(),bnk.end()),bnk.end()); } int qmpMidiOutFluid::getPolyphone() { diff --git a/core/qmpmidioutfluid.hpp b/core/qmpmidioutfluid.hpp index 963f9df..72197e7 100644 --- a/core/qmpmidioutfluid.hpp +++ b/core/qmpmidioutfluid.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "../include/qmpcorepublic.hpp" #include class IFluidSettings @@ -22,6 +23,9 @@ class qmpMidiOutFluid:public qmpMidiOutDevice,public IFluidSettings fluid_settings_t* settings; fluid_synth_t* synth; fluid_audio_driver_t* adriver; + std::vector> bnk; + std::unordered_map> pst; + void update_preset_list(); public: qmpMidiOutFluid(); ~qmpMidiOutFluid(); @@ -36,13 +40,17 @@ class qmpMidiOutFluid:public qmpMidiOutDevice,public IFluidSettings void reset(uint8_t ch); void onMapped(uint8_t ch,int refcnt); void onUnmapped(uint8_t ch,int refcnt); + std::vector> getBankList(); + std::vector> getPresets(int bank); + std::string getPresetName(uint16_t bank,uint8_t preset); + bool getChannelPreset(int ch,uint16_t *bank,uint8_t *preset,std::string &presetname); + uint8_t getInitialCCValue(uint8_t cc); //FluidSynth specific stuff void setOptStr(const char* opt,const char* val); void setOptInt(const char* opt,int val); void setOptNum(const char* opt,double val); void loadSFont(const char* path); int getSFCount(); - std::vector,std::string>> listPresets(); int getPolyphone(); int getMaxPolyphone(); diff --git a/core/qmpmidioutrtmidi.cpp b/core/qmpmidioutrtmidi.cpp index 2d6d41f..0ff2c86 100644 --- a/core/qmpmidioutrtmidi.cpp +++ b/core/qmpmidioutrtmidi.cpp @@ -1,8 +1,144 @@ +#include #include #include +#include #include #include RT_MIDI_H #include "qmpmidioutrtmidi.hpp" + +void split(std::string s,char c,std::deque& v) +{ + v.clear(); + for(size_t anch=0;;) + { + std::string sec; + if(s.find(c,anch)==std::string::npos) + sec=s.substr(anch); + else sec=s.substr(anch,s.find(c,anch)-anch); + if(!sec.empty())v.push_back(sec); + if(s.find(c,anch)==std::string::npos)break; + anch=s.find(c,anch)+1; + } +} + +qmpDeviceInitializer* qmpDeviceInitializer::parse(const char* path) +{ + qmpDeviceInitializer *ret=new qmpDeviceInitializer(); + ret->initseq.eventList.clear(); + FILE* f=fopen(path, "r"); + if(!f)return nullptr; + + bool st_inmapping=false; + char buf[1024]; + int ln=0; + int cmsb=-1,clsb=-1; + + //writing such a bad parser makes me want my money for + //the credits from "compiler principles" back... + auto h2d=[](char c)->char{return 'F'>=c&&c>='A'?c-'A'+10:'9'>=c&&c>='0'?c-'0':-1;}; + auto hh2d=[](const char *c)->int + { + if(!c||!*c||strlen(c)>2)return -1; + int x=-1,r; + r=sscanf(c,"%x",&x); + (x<0||x>0xff)&&(x=-1); + return r==1?x:-1; + }; +#define err(e) {delete ret;return fprintf(stderr,"line %d: %s",ln,e),nullptr;} + while(fgets(buf,1024,f)) + { + ++ln; + if(buf[0]=='#')continue; + std::string b(buf); + while(b.length()&&b.back()=='\n')b.pop_back(); + std::deque tok; + split(b,' ',tok); + if(!tok.size())continue; + if(tok.front()=="MAP") + { + if(st_inmapping) + err("invalid command") + st_inmapping=true; + } + else if(tok.front()=="ENDMAP") + { + if(!st_inmapping) + err("invalid command") + st_inmapping=false; + } + else if(tok.front()=="X") + { + if(st_inmapping) + err("invalid command") + tok.pop_front(); + std::string sysx; + for(auto&i:tok)sysx+=i; + SEvent ev; + ev.type=0xF0; + ev.str=""; + for(auto i=sysx.begin();i!=sysx.end();++i) + { + char hn=h2d((char)toupper(*i)); + if(hn<0)err("invalid sysex") + if(++i==sysx.end())err("invalid sysex") + char ln=h2d((char)toupper(*i)); + ev.str.push_back((char)(hn<<4|ln)); + } + ret->initseq.appendEvent(ev); + } + else if(tok.front()=="C") + { + if(tok.size()!=4)err("invalid control") + int ch=hh2d(tok[1].c_str()); + int cc=hh2d(tok[2].c_str()); + int cv=hh2d(tok[3].c_str()); + if(!~cc||!~cv)err("invalid control parameters") + if(ch==0xff) + { + for(int i=0;i<16;++i) + { + SEvent e; + e.type=(uint8_t)(0xB0|i); + e.p1=(uint8_t)cc; + e.p2=(uint8_t)cv; + ret->initseq.appendEvent(e); + } + } + else if(ch>=0&&ch<0x10) + { + SEvent e; + e.type=(uint8_t)(0xB0|ch); + e.p1=(uint8_t)cc; + e.p2=(uint8_t)cv; + ret->initseq.appendEvent(e); + } + else err("invalid channel") + } + else if(tok.front()=="IV") + { + int ci=0; + tok.pop_front(); + for(auto&tk:tok) + { + int v=0,rep=1; + if(tk.find(',')!=std::string::npos) + sscanf(tk.c_str(),"%x,%d",&v,&rep); + else sscanf(tk.c_str(),"%x",&v); + if(v>0xff||v<0)err("invalid init vector value") + for(int i=0;i=130)err("invalid init vector") + ret->initv[ci++]=(uint8_t)v; + } + } + } + } +#undef err + + fclose(f); + return ret; +} + qmpMidiOutRtMidi::qmpMidiOutRtMidi(unsigned _portid) { portid=_portid; @@ -91,6 +227,21 @@ void qmpMidiOutRtMidi::onUnmapped(uint8_t ch,int refcnt) panic(ch); if(!refcnt&&outport)outport->closePort(); } +std::vector> qmpMidiOutRtMidi::getBankList() +{ +} +std::vector> qmpMidiOutRtMidi::getPresets(int bank) +{ +} +std::string qmpMidiOutRtMidi::getPresetName(uint16_t bank,uint8_t preset) +{ +} +bool qmpMidiOutRtMidi::getChannelPreset(int ch,uint16_t *bank,uint8_t *preset,std::string &presetname) +{ +} +uint8_t qmpMidiOutRtMidi::getInitialCCValue(uint8_t cc) +{ +} RtMidiOut* qmpRtMidiManager::dummy=nullptr; void qmpRtMidiManager::createDevices() diff --git a/core/qmpmidioutrtmidi.hpp b/core/qmpmidioutrtmidi.hpp index 48ee0cf..23adec6 100644 --- a/core/qmpmidioutrtmidi.hpp +++ b/core/qmpmidioutrtmidi.hpp @@ -1,9 +1,23 @@ #ifndef QMPMIDIMAPPERS_H #define QMPMIDIMAPPERS_H +#include #include #define QMP_MAIN #include "../include/qmpcorepublic.hpp" #include RT_MIDI_H +struct qmpDeviceInitializer +{ + CMidiTrack initseq; + struct BankStore + { + std::unordered_map presets; + std::string bankname; + }; + std::unordered_map banks; + uint8_t initv[130]; + + static qmpDeviceInitializer* parse(const char* path); +}; class qmpMidiOutRtMidi:public qmpMidiOutDevice { private: @@ -22,6 +36,11 @@ public: void reset(uint8_t ch); void onMapped(uint8_t ch,int refcnt); void onUnmapped(uint8_t ch,int refcnt); + std::vector> getBankList(); + std::vector> getPresets(int bank); + std::string getPresetName(uint16_t bank,uint8_t preset); + bool getChannelPreset(int ch,uint16_t *bank,uint8_t *preset,std::string &presetname); + uint8_t getInitialCCValue(uint8_t cc); }; class qmpRtMidiManager { diff --git a/core/qmpmidiplay.cpp b/core/qmpmidiplay.cpp index 28ca9e7..bbf1c3a 100644 --- a/core/qmpmidiplay.cpp +++ b/core/qmpmidiplay.cpp @@ -241,7 +241,7 @@ void CMidiPlayer::fileTimer2Pass() memset(ccc,0,sizeof(ccc));memset(rpnid,0xFF,sizeof(rpnid));memset(rpnval,0xFF,sizeof(rpnval)); for(int i=0;i<16;++i) { - ccc[i][7]=100;ccc[i][8]=64;ccc[i][10]=64;ccc[i][11]=127; + ccc[i][7]=100;ccc[i][8]=64;ccc[i][10]=64; ccc[i][11]=127;ccc[i][71]=64;ccc[i][72]=64; ccc[i][73]=64;ccc[i][74]=64;ccc[i][75]=64; ccc[i][76]=64;ccc[i][77]=64;ccc[i][78]=64; @@ -427,19 +427,6 @@ uint32_t CMidiPlayer::isFinished(){return finished;} void CMidiPlayer::setResumed(){resumed=true;} void CMidiPlayer::setWaitVoice(bool wv){waitvoice=wv;} -void CMidiPlayer::getChannelPreset(int ch,int *b,int *p,char *name) -{ - if(mappedoutput[ch]) - { - *b=((int)chstatus[ch][0]<<7)|chstatus[ch][32]; - *p=chstatus[ch][128]; - strcpy(name,""); - } - else - { - internalFluid->getChannelInfo(ch,b,p,name); - } -} void CMidiPlayer::setChannelPreset(int ch,int b,int p) { chstatus[ch][128]=p; @@ -510,6 +497,10 @@ int CMidiPlayer::getChannelOutput(int ch) { return mappedoutput[ch]; } +qmpMidiOutDevice* CMidiPlayer::getChannelOutputDevice(int ch) +{ + return mididev[mappedoutput[ch]].dev; +} void CMidiPlayer::setChannelOutput(int ch,int outid) { int origoutput=mappedoutput[ch]; diff --git a/core/qmpmidiplay.hpp b/core/qmpmidiplay.hpp index f42c98b..da9e9ef 100644 --- a/core/qmpmidiplay.hpp +++ b/core/qmpmidiplay.hpp @@ -141,7 +141,6 @@ class CMidiPlayer void sendSysX(bool send); void setChannelPreset(int ch,int b,int p); - void getChannelPreset(int ch,int *b,int *p,char *name); void setMute(int ch,bool m); void setSolo(int ch,bool s); bool getChannelMask(int ch); @@ -154,6 +153,7 @@ class CMidiPlayer void unregisterMidiOutDevice(std::string name); std::vector getMidiOutDevices(); int getChannelOutput(int ch); + qmpMidiOutDevice* getChannelOutputDevice(int ch); void setChannelOutput(int ch,int outid); uint8_t* getChstates(); int setEventHandlerCB(ICallBack *cb,void *userdata); diff --git a/core/qmpmidiread.cpp b/core/qmpmidiread.cpp index 7f5bdfc..48a149d 100644 --- a/core/qmpmidiread.cpp +++ b/core/qmpmidiread.cpp @@ -94,7 +94,8 @@ int CSMFReader::read_event()//returns 0 if End of Track encountered uint32_t len=read_varlen();char* str=nullptr; if(len<=1024&&len>0)str=new char[len+8]; if(str)fread(str,1,len,f);else fseek(f,len,SEEK_CUR); - if(str)str[len]='\0'; + std::string sstr; + if(str){str[len]='\0';sstr=std::string(str,len);} switch(metatype) { case 0x00://Sequence Number @@ -108,24 +109,24 @@ int CSMFReader::read_event()//returns 0 if End of Track encountered return 0; case 0x51://Set Tempo assert(len==3); - curTrack->appendEvent(SEvent(curid,curt,type,metatype,0,str)); + curTrack->appendEvent(SEvent(curid,curt,type,metatype,0,sstr)); break; case 0x54://SMTPE offset, not handled. assert(len==5); break; case 0x58://Time signature assert(len==4); - curTrack->appendEvent(SEvent(curid,curt,type,metatype,0,str)); + curTrack->appendEvent(SEvent(curid,curt,type,metatype,0,sstr)); break; case 0x59://Key signature assert(len==2); - curTrack->appendEvent(SEvent(curid,curt,type,metatype,0,str)); + curTrack->appendEvent(SEvent(curid,curt,type,metatype,0,sstr)); break; case 0x01:case 0x02:case 0x03: case 0x04:case 0x05:case 0x06: case 0x07:case 0x7F:default://text-like meta { - curTrack->appendEvent(SEvent(curid,curt,type,metatype,0,str)); + curTrack->appendEvent(SEvent(curid,curt,type,metatype,0,sstr)); if(str&&metatype==0x03&&!ret->title) { ret->title=new char[len+8]; diff --git a/include/qmpcorepublic.hpp b/include/qmpcorepublic.hpp index a4949ac..34e4ea6 100644 --- a/include/qmpcorepublic.hpp +++ b/include/qmpcorepublic.hpp @@ -24,6 +24,8 @@ struct SEvent p1=_p1;p2=_p2;flags=0; if(s)str=std::string(s);else str=""; } + SEvent(uint32_t _iid,uint32_t _t,uint8_t _tp,uint8_t _p1,uint8_t _p2,std::string s): + iid(_iid),time(_t),type(_tp),p1(_p1),p2(_p2),str(s){} friend bool operator <(const SEvent& a,const SEvent& b){return a.time-b.time?a.time> getBankList()=0; + virtual std::vector> getPresets(int bank)=0; + virtual std::string getPresetName(uint16_t bank,uint8_t preset)=0; + virtual bool getChannelPreset(int ch,uint16_t *bank,uint8_t *preset,std::string &presetname)=0; + virtual uint8_t getInitialCCValue(uint8_t cc)=0; virtual ~qmpMidiOutDevice(){} }; //Main plugin interface. diff --git a/qmidiplayer-desktop/qmpchanneleditor.cpp b/qmidiplayer-desktop/qmpchanneleditor.cpp index 206a2fa..71dd455 100644 --- a/qmidiplayer-desktop/qmpchanneleditor.cpp +++ b/qmidiplayer-desktop/qmpchanneleditor.cpp @@ -25,9 +25,9 @@ void qmpChannelEditor::setupWindow(int chid) char str[256];if(~chid)ch=chid; setWindowTitle(tr("Channel Parameter Editor - Channel #%1").arg(ch+1)); CMidiPlayer* player=qmpMainWindow::getInstance()->getPlayer(); - int b,p; - player->getChannelPreset(ch,&b,&p,str); - ui->lbPresetName->setText(str); + uint16_t b;uint8_t p;std::string pstn; + player->getChannelOutputDevice(ch)->getChannelPreset(ch,&b,&p,pstn); + ui->lbPresetName->setText(pstn.c_str()); sprintf(str,"BK: %03d",b);ui->lbBank->setText(str); sprintf(str,"PC: %03d",p);ui->lbPreset->setText(str); ui->lbChannelNumber->setText(QString::number(ch+1)); diff --git a/qmidiplayer-desktop/qmpchannelswindow.cpp b/qmidiplayer-desktop/qmpchannelswindow.cpp index 8968bed..5a6a2de 100644 --- a/qmidiplayer-desktop/qmpchannelswindow.cpp +++ b/qmidiplayer-desktop/qmpchannelswindow.cpp @@ -153,10 +153,11 @@ void qmpChannelsWindow::channelWindowsUpdate() } for(int i=0;i<16;++i) { - char data[128],nm[256]; - int b,p; - qmpMainWindow::getInstance()->getPlayer()->getChannelPreset(i,&b,&p,nm); - sprintf(data,"%03d:%03d %s",b,p,nm); + char data[128]; + std::string nm; + uint16_t b;uint8_t p; + qmpMainWindow::getInstance()->getPlayer()->getChannelOutputDevice(i)->getChannelPreset(i,&b,&p,nm); + sprintf(data,"%03d:%03d %s",b,p,nm.c_str()); if(fused) { if(strcmp((ui->twChannels->item(i,4))-> diff --git a/qmidiplayer-desktop/qmpplugin.cpp b/qmidiplayer-desktop/qmpplugin.cpp index 8655dff..2339625 100644 --- a/qmidiplayer-desktop/qmpplugin.cpp +++ b/qmidiplayer-desktop/qmpplugin.cpp @@ -153,11 +153,11 @@ int qmpPluginAPI::getChannelCC(int ch,int cc) {return qmw&&qmw->getPlayer()?qmw->getPlayer()->getCC(ch,cc):0;} int qmpPluginAPI::getChannelPreset(int ch) { - int b,p;char nm[256]; + uint16_t b;uint8_t p;std::string nm; if(qmw&&qmw->getPlayer()) { - qmw->getPlayer()->getChannelPreset(ch,&b,&p,nm); - return p; + if(qmw->getPlayer()->getChannelOutputDevice(ch)->getChannelPreset(ch,&b,&p,nm))return p; + return qmw->getPlayer()->getCC(ch,128); } return 0; } @@ -173,11 +173,12 @@ std::wstring qmpPluginAPI::getWTitle() {return qmw?qmw->getWTitle():L"";} std::string qmpPluginAPI::getChannelPresetString(int ch) { - int b,p;char nm[256],ret[320];ret[0]=0; + uint16_t b;uint8_t p;char ret[320];ret[0]=0; + std::string nm; if(qmw&&qmw->getPlayer()) { - qmw->getPlayer()->getChannelPreset(ch,&b,&p,nm); - snprintf(ret,320,"%03d:%03d %s",b,p,nm); + qmw->getPlayer()->getChannelOutputDevice(ch)->getChannelPreset(ch,&b,&p,nm); + snprintf(ret,320,"%03d:%03d %s",b,p,nm.c_str()); } return std::string(ret); } diff --git a/qmidiplayer-desktop/qmppresetselect.cpp b/qmidiplayer-desktop/qmppresetselect.cpp index 8afea2b..a32aa99 100644 --- a/qmidiplayer-desktop/qmppresetselect.cpp +++ b/qmidiplayer-desktop/qmppresetselect.cpp @@ -20,29 +20,25 @@ void qmpPresetSelector::showEvent(QShowEvent *e) memset(presets,0,sizeof(presets)); CMidiPlayer *plyr=qmpMainWindow::getInstance()->getPlayer(); if(!plyr->fluid()->getSFCount())return e->ignore(); - std::vector,std::string>> - presetlist=plyr->fluid()->listPresets(); - for(auto &i:presetlist) - strcpy(presets[i.first.first][i.first.second],i.second.c_str()); ui->lwBankSelect->clear(); ui->lwPresetSelect->clear(); - for(int i=0;i<=128;++i) - { - int b=0; - for(int j=0;j<128;++j)if(strlen(presets[i][j])){b=1;break;} - if(b)ui->lwBankSelect->addItem(QString::number(i)); - } e->accept(); } void qmpPresetSelector::setupWindow(int chid) { CMidiPlayer *plyr=qmpMainWindow::getInstance()->getPlayer(); if(!plyr->fluid()->getSFCount())return; - ch=chid;int b=0,p=0,r;char name[256]; + ch=chid;int r;char name[256]; + uint16_t b;uint8_t p; + std::string pstname; sprintf(name,"Preset Selection - Channel #%d",ch+1); setWindowTitle(name); - plyr->getChannelPreset(chid,&b,&p,name); - if(plyr->getChannelOutput(chid)){ + r=plyr->getChannelOutputDevice(ch)->getChannelPreset(ch,&b,&p,pstname); + ui->lwBankSelect->blockSignals(true); + ui->lwBankSelect->clear(); + ui->lwPresetSelect->clear(); + ui->lwBankSelect->blockSignals(false); + if(plyr->getChannelOutputDevice(ch)->getBankList().empty()){ ui->lwPresetSelect->setEnabled(false); ui->lwBankSelect->setEnabled(false); ui->spCustomLSB->setEnabled(true); @@ -58,21 +54,20 @@ void qmpPresetSelector::setupWindow(int chid) ui->spCustomLSB->setEnabled(false); ui->spCustomMSB->setEnabled(false); ui->spCustomPC->setEnabled(false); - for(int i=0;ilwBankSelect->count();++i){ - sscanf(ui->lwBankSelect->item(i)->text().toStdString().c_str(),"%3d",&r); - if(r==b){ui->lwBankSelect->setCurrentRow(i);break;} + ui->lwBankSelect->blockSignals(true); + for(auto&i:plyr->getChannelOutputDevice(ch)->getBankList()) + { + snprintf(name,256,"%03d %s",i.first,i.second.c_str()); + ui->lwBankSelect->addItem(name); + if(i.first==b)ui->lwBankSelect->setCurrentRow(ui->lwBankSelect->count()-1); } - r=0; - ui->lwPresetSelect->clear(); - for(int i=0,cr=0;i<128;++i) - if(strlen(presets[b][i])) + ui->lwBankSelect->blockSignals(false); + for(auto&i:plyr->getChannelOutputDevice(ch)->getPresets(b)) { - sprintf(name,"%03d %s",i,presets[b][i]); - if(i==p)r=cr; + snprintf(name,256,"%03d %s",i.first,i.second.c_str()); ui->lwPresetSelect->addItem(name); - cr++; + if(i.first==p)ui->lwPresetSelect->setCurrentRow(ui->lwPresetSelect->count()-1); } - ui->lwPresetSelect->setCurrentRow(r); } } @@ -109,14 +104,15 @@ void qmpPresetSelector::on_lwPresetSelect_itemDoubleClicked() void qmpPresetSelector::on_lwBankSelect_currentRowChanged() { + fprintf(stderr,"bs cr changed\n"); ui->lwPresetSelect->clear(); if(!ui->lwBankSelect->currentItem())return; - char name[30];int b; + char name[256];int b; sscanf(ui->lwBankSelect->currentItem()->text().toStdString().c_str(),"%d",&b); - for(int i=0;i<128;++i) - if(strlen(presets[b][i])) + CMidiPlayer *plyr=qmpMainWindow::getInstance()->getPlayer(); + for(auto&i:plyr->getChannelOutputDevice(ch)->getPresets(b)) { - sprintf(name,"%03d %s",i,presets[b][i]); + snprintf(name,256,"%03d %s",i.first,i.second.c_str()); ui->lwPresetSelect->addItem(name); } } diff --git a/visualization/visualization.pro b/visualization/visualization.pro index 646e301..892680e 100644 --- a/visualization/visualization.pro +++ b/visualization/visualization.pro @@ -36,12 +36,12 @@ unix { INCLUDEPATH += /home/chrisoft/devel/SMELT/include/ /usr/include/freetype2 LIBS += -L/home/chrisoft/devel/SMELT/smelt/glfw/ LIBS += -L/home/chrisoft/devel/SMELT/extensions/ - LIBS += -lstdc++ -lfreetype -lz -lsmeltext -lsmelt-dumb -lCxImage -ljpeg -lpng -lglfw -lGLEW -lGL + LIBS += -lstdc++ -lfreetype -lz -lsmeltext -lsmelt-dumb -lIL -ljpeg -lpng -lglfw -lGLEW -lGL }else{ INCLUDEPATH += $$(SMELT_DIR)/include/ /usr/include/freetype2 LIBS += -L$$(SMELT_DIR)/smelt/glfw/ LIBS += -L$$(SMELT_DIR)/extensions/ - LIBS += -lstdc++ -lfreetype -lz -lsmeltext -lsmelt-dumb -lCxImage -ljpeg -lpng -lglfw -lGLEW -lGL + LIBS += -lstdc++ -lfreetype -lz -lsmeltext -lsmelt-dumb -lIL -ljpeg -lpng -lglfw -lGLEW -lGL } } win32 { -- cgit v1.2.3